Sfoglia il codice sorgente

Added email type options to rules

Will Browning 3 anni fa
parent
commit
21fbfd0335

+ 8 - 2
app/Http/Controllers/Api/RuleController.php

@@ -34,7 +34,10 @@ class RuleController extends Controller
             'name' => $request->name,
             'conditions' => $conditions,
             'actions' => $actions,
-            'operator' => $request->operator
+            'operator' => $request->operator,
+            'forwards' => $request->forwards ?? false,
+            'replies' => $request->replies ?? false,
+            'sends' => $request->sends ?? false
         ]);
 
         return new RuleResource($rule->refresh());
@@ -56,7 +59,10 @@ class RuleController extends Controller
             'name' => $request->name,
             'conditions' => $conditions,
             'actions' => $actions,
-            'operator' => $request->operator
+            'operator' => $request->operator,
+            'forwards' => $request->forwards ?? false,
+            'replies' => $request->replies ?? false,
+            'sends' => $request->sends ?? false
         ]);
 
         return new RuleResource($rule->refresh());

+ 4 - 1
app/Http/Requests/StoreRuleRequest.php

@@ -89,7 +89,10 @@ class StoreRuleRequest extends FormRequest
             'operator' => [
                 'required',
                 'in:AND,OR'
-            ]
+            ],
+            'forwards' => 'boolean',
+            'replies' => 'boolean',
+            'sends' => 'boolean'
         ];
     }
 }

+ 3 - 0
app/Http/Resources/RuleResource.php

@@ -16,6 +16,9 @@ class RuleResource extends JsonResource
             'conditions' => $this->conditions,
             'actions' => $this->actions,
             'operator' => $this->operator,
+            'forwards' => $this->forwards,
+            'replies' => $this->replies,
+            'sends' => $this->sends,
             'active' => $this->active,
             'created_at' => $this->created_at->toDateTimeString(),
             'updated_at' => $this->updated_at->toDateTimeString(),

+ 1 - 1
app/Mail/ForwardEmail.php

@@ -250,7 +250,7 @@ class ForwardEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
 
         $this->replacedSubject = $this->user->email_subject ? ' with subject "' . base64_decode($this->emailSubject) . '"' : null;
 
-        $this->checkRules();
+        $this->checkRules('Forwards');
 
         $this->email->with([
             'location' => $this->bannerLocation,

+ 1 - 1
app/Mail/ReplyToEmail.php

@@ -166,7 +166,7 @@ class ReplyToEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
             );
         }
 
-        $this->checkRules();
+        $this->checkRules('Replies');
 
         $this->email->with([
             'shouldBlock' => $this->size === 0

+ 1 - 1
app/Mail/SendFromEmail.php

@@ -152,7 +152,7 @@ class SendFromEmail extends Mailable implements ShouldQueue, ShouldBeEncrypted
             );
         }
 
-        $this->checkRules();
+        $this->checkRules('Sends');
 
         $this->email->with([
             'shouldBlock' => $this->size === 0

+ 6 - 0
app/Models/Rule.php

@@ -19,6 +19,9 @@ class Rule extends Model
         'conditions',
         'actions',
         'operator',
+        'forwards',
+        'replies',
+        'sends',
         'active',
         'order'
     ];
@@ -32,6 +35,9 @@ class Rule extends Model
         'id' => 'string',
         'user_id' => 'string',
         'active' => 'boolean',
+        'forwards' => 'boolean',
+        'replies' => 'boolean',
+        'sends' => 'boolean',
         'conditions' => 'array',
         'actions' => 'array'
     ];

+ 24 - 0
app/Models/User.php

@@ -195,6 +195,30 @@ class User extends Authenticatable implements MustVerifyEmail
         return $this->rules()->where('active', true)->orderBy('order');
     }
 
+    /**
+     * Get all of the user's active rules in the correct order that should be run of forwards.
+     */
+    public function activeRulesForForwardsOrdered()
+    {
+        return $this->rules()->where('active', true)->where('forwards', true)->orderBy('order');
+    }
+
+    /**
+     * Get all of the user's active rules in the correct order that should be run of forwards.
+     */
+    public function activeRulesForRepliesOrdered()
+    {
+        return $this->rules()->where('active', true)->where('replies', true)->orderBy('order');
+    }
+
+    /**
+     * Get all of the user's active rules in the correct order that should be run of forwards.
+     */
+    public function activeRulesForSendsOrdered()
+    {
+        return $this->rules()->where('active', true)->where('sends', true)->orderBy('order');
+    }
+
     /**
      * Get all of the user's additional usernames.
      */

+ 3 - 2
app/Traits/CheckUserRules.php

@@ -6,9 +6,10 @@ use Illuminate\Support\Str;
 
 trait CheckUserRules
 {
-    public function checkRules()
+    public function checkRules(String $emailType)
     {
-        $this->user->activeRulesOrdered()->each(function ($rule) {
+        $method = "activeRulesFor{$emailType}Ordered";
+        $this->user->{$method}->each(function ($rule) {
             // Check if the conditions of the rule are satisfied
             if ($this->ruleConditionsSatisfied($rule->conditions, $rule->operator)) {
                 // Apply actions for that rule

File diff suppressed because it is too large
+ 231 - 249
composer.lock


+ 2 - 2
config/version.yml

@@ -5,9 +5,9 @@ current:
   major: 0
   minor: 8
   patch: 7
-  prerelease: 2-g339af30
+  prerelease: 3-g9bfc7ba
   buildmetadata: ''
-  commit: 339af3
+  commit: 9bfc7b
   timestamp:
     year: 2020
     month: 10

+ 36 - 0
database/migrations/2021_12_03_155539_add_email_types_to_rules_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddEmailTypesToRulesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('rules', function (Blueprint $table) {
+            $table->boolean('sends')->after('operator')->default(false);
+            $table->boolean('replies')->after('operator')->default(false);
+            $table->boolean('forwards')->after('operator')->default(false);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('rules', function (Blueprint $table) {
+            $table->dropColumn('sends');
+            $table->dropColumn('replies');
+            $table->dropColumn('forwards');
+        });
+    }
+}

+ 189 - 205
package-lock.json

@@ -1589,9 +1589,9 @@
             }
         },
         "node_modules/@discoveryjs/json-ext": {
-            "version": "0.5.5",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz",
-            "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==",
+            "version": "0.5.6",
+            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
+            "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==",
             "engines": {
                 "node": ">=10.0.0"
             }
@@ -1629,9 +1629,9 @@
             }
         },
         "node_modules/@popperjs/core": {
-            "version": "2.10.2",
-            "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
-            "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==",
+            "version": "2.11.0",
+            "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.0.tgz",
+            "integrity": "sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==",
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/popperjs"
@@ -1791,9 +1791,9 @@
             "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
         },
         "node_modules/@types/node": {
-            "version": "16.11.10",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz",
-            "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA=="
+            "version": "16.11.11",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
+            "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw=="
         },
         "node_modules/@types/parse-json": {
             "version": "4.0.0",
@@ -2827,9 +2827,9 @@
             }
         },
         "node_modules/caniuse-lite": {
-            "version": "1.0.30001283",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
-            "integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg==",
+            "version": "1.0.30001284",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001284.tgz",
+            "integrity": "sha512-t28SKa7g6kiIQi6NHeOcKrOrGMzCRrXvlasPwWC26TH2QNdglgzQIRUuJ0cR3NeQPH+5jpuveeeSFDLm2zbkEw==",
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/browserslist"
@@ -2989,9 +2989,9 @@
             }
         },
         "node_modules/collect.js": {
-            "version": "4.29.0",
-            "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.29.0.tgz",
-            "integrity": "sha512-yhgGYEsLEcqnLT1NmRlN1+1euoz9SDhxQ4QyDhWYsKoWsg7252PKA5++dWaDs8mdFxbkmXDXQUaHXI9J2eTPkQ=="
+            "version": "4.29.3",
+            "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.29.3.tgz",
+            "integrity": "sha512-/6idZ7r3B25Q4cForbiHJ7+aqupcgMEtrKRn9D3viCbLw+YuNFjd23HwDH89Y2cU4jlhkwksD80nZFKtNE25Gw=="
         },
         "node_modules/color": {
             "version": "4.0.2",
@@ -3019,9 +3019,9 @@
             "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
         },
         "node_modules/color-string": {
-            "version": "1.7.4",
-            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.7.4.tgz",
-            "integrity": "sha512-nVdUvPVgZMpRQad5dcsCMOSB5BXLljklTiaxS6ehhKxDsAI5sD7k5VmFuBt1y3Rlym8uulc/ANUN/bMWtBu6Sg==",
+            "version": "1.9.0",
+            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
+            "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
             "dependencies": {
                 "color-name": "^1.0.0",
                 "simple-swizzle": "^0.2.2"
@@ -3208,11 +3208,11 @@
             "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "node_modules/core-js-compat": {
-            "version": "3.19.1",
-            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.1.tgz",
-            "integrity": "sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g==",
+            "version": "3.19.2",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.2.tgz",
+            "integrity": "sha512-ObBY1W5vx/LFFMaL1P5Udo4Npib6fu+cMokeziWkA8Tns4FcDemKF5j9JvaI5JhdkW8EQJQGJN1EcrzmEwuAqQ==",
             "dependencies": {
-                "browserslist": "^4.17.6",
+                "browserslist": "^4.18.1",
                 "semver": "7.0.0"
             },
             "funding": {
@@ -3411,9 +3411,9 @@
             }
         },
         "node_modules/css-select/node_modules/domhandler": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-            "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+            "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
             "dependencies": {
                 "domelementtype": "^2.2.0"
             },
@@ -3472,11 +3472,11 @@
             }
         },
         "node_modules/cssnano": {
-            "version": "5.0.11",
-            "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.11.tgz",
-            "integrity": "sha512-5SHM31NAAe29jvy0MJqK40zZ/8dGlnlzcfHKw00bWMVFp8LWqtuyPSFwbaoIoxvt71KWJOfg8HMRGrBR3PExCg==",
+            "version": "5.0.12",
+            "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.12.tgz",
+            "integrity": "sha512-U38V4x2iJ3ijPdeWqUrEr4eKBB5PbEKsNP5T8xcik2Au3LeMtiMHX0i2Hu9k51FcKofNZumbrcdC6+a521IUHg==",
             "dependencies": {
-                "cssnano-preset-default": "^5.1.7",
+                "cssnano-preset-default": "^5.1.8",
                 "is-resolvable": "^1.1.0",
                 "lilconfig": "^2.0.3",
                 "yaml": "^1.10.2"
@@ -3493,9 +3493,9 @@
             }
         },
         "node_modules/cssnano-preset-default": {
-            "version": "5.1.7",
-            "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.7.tgz",
-            "integrity": "sha512-bWDjtTY+BOqrqBtsSQIbN0RLGD2Yr2CnecpP0ydHNafh9ZUEre8c8VYTaH9FEbyOt0eIfEUAYYk5zj92ioO8LA==",
+            "version": "5.1.8",
+            "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.8.tgz",
+            "integrity": "sha512-zWMlP0+AMPBVE852SqTrP0DnhTcTA2C1wAF92TKZ3Va+aUVqLIhkqKlnJIXXdqXD7RN+S1ujuWmNpvrJBiM/vg==",
             "dependencies": {
                 "css-declaration-sorter": "^6.0.3",
                 "cssnano-utils": "^2.0.1",
@@ -3522,7 +3522,7 @@
                 "postcss-normalize-url": "^5.0.3",
                 "postcss-normalize-whitespace": "^5.0.1",
                 "postcss-ordered-values": "^5.0.2",
-                "postcss-reduce-initial": "^5.0.1",
+                "postcss-reduce-initial": "^5.0.2",
                 "postcss-reduce-transforms": "^5.0.1",
                 "postcss-svgo": "^5.0.3",
                 "postcss-unique-selectors": "^5.0.2"
@@ -3557,9 +3557,9 @@
             }
         },
         "node_modules/date-fns": {
-            "version": "2.26.0",
-            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.26.0.tgz",
-            "integrity": "sha512-VQI812dRi3cusdY/fhoBKvc6l2W8BPWU1FNVnFH9Nttjx4AFBRzfSVb/Eyc7jBT6e9sg1XtAGsYpBQ6c/jygbg==",
+            "version": "2.27.0",
+            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.27.0.tgz",
+            "integrity": "sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q==",
             "engines": {
                 "node": ">=0.11"
             },
@@ -3579,9 +3579,9 @@
             "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
         },
         "node_modules/debug": {
-            "version": "4.3.2",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-            "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+            "version": "4.3.3",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+            "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
             "dependencies": {
                 "ms": "2.1.2"
             },
@@ -3800,9 +3800,9 @@
             }
         },
         "node_modules/dom-serializer/node_modules/domhandler": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-            "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+            "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
             "dependencies": {
                 "domelementtype": "^2.2.0"
             },
@@ -3861,9 +3861,9 @@
             }
         },
         "node_modules/domutils/node_modules/domhandler": {
-            "version": "4.2.2",
-            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-            "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+            "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
             "dependencies": {
                 "domelementtype": "^2.2.0"
             },
@@ -3902,9 +3902,9 @@
             "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "node_modules/electron-to-chromium": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.3.tgz",
-            "integrity": "sha512-hfpppjYhqIZB8jrNb0rNceQRkSnBN7QJl3W26O1jUv3F3BkQknqy1YTqVXkFnIcFtBc3Qnv5M7r5Lez2iOLgZA=="
+            "version": "1.4.10",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.10.tgz",
+            "integrity": "sha512-tFgA40Iq2oy4k2PnZrLJowbgpij+lD6ZLxkw8Ht1NKTYyN8dvSvC5xlo8X0WW2jqhKSzITrbr5mpB4/AZ/8OUA=="
         },
         "node_modules/elliptic": {
             "version": "6.5.4",
@@ -4821,9 +4821,9 @@
             "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
         },
         "node_modules/http-parser-js": {
-            "version": "0.5.3",
-            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz",
-            "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg=="
+            "version": "0.5.5",
+            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
+            "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA=="
         },
         "node_modules/http-proxy": {
             "version": "1.18.1",
@@ -5380,9 +5380,9 @@
             }
         },
         "node_modules/jest-worker": {
-            "version": "27.3.1",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz",
-            "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==",
+            "version": "27.4.2",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz",
+            "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==",
             "dependencies": {
                 "@types/node": "*",
                 "merge-stream": "^2.0.0",
@@ -6145,14 +6145,6 @@
                 "which": "^2.0.2"
             }
         },
-        "node_modules/node-notifier/node_modules/uuid": {
-            "version": "8.3.2",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-            "bin": {
-                "uuid": "dist/bin/uuid"
-            }
-        },
         "node_modules/node-releases": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
@@ -6640,9 +6632,9 @@
             }
         },
         "node_modules/postcss": {
-            "version": "8.4.1",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.1.tgz",
-            "integrity": "sha512-WqLs/TTzXdG+/A4ZOOK9WDZiikrRaiA+eoEb/jz2DT9KUhMNHgP7yKPO8vwi62ZCsb703Gwb7BMZwDzI54Y2Ag==",
+            "version": "8.4.4",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.4.tgz",
+            "integrity": "sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q==",
             "dependencies": {
                 "nanoid": "^3.1.30",
                 "picocolors": "^1.0.0",
@@ -6801,12 +6793,12 @@
             }
         },
         "node_modules/postcss-loader": {
-            "version": "6.2.0",
-            "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.0.tgz",
-            "integrity": "sha512-H9hv447QjQJVDbHj3OUdciyAXY3v5+UDduzEytAlZCVHCpNAAg/mCSwhYYqZr9BiGYhmYspU8QXxZwiHTLn3yA==",
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz",
+            "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==",
             "dependencies": {
                 "cosmiconfig": "^7.0.0",
-                "klona": "^2.0.4",
+                "klona": "^2.0.5",
                 "semver": "^7.3.5"
             },
             "engines": {
@@ -7133,11 +7125,11 @@
             }
         },
         "node_modules/postcss-reduce-initial": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz",
-            "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==",
+            "version": "5.0.2",
+            "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.2.tgz",
+            "integrity": "sha512-v/kbAAQ+S1V5v9TJvbGkV98V2ERPdU6XvMcKMjqAlYiJ2NtsHGlKYLPjWWcXlaTKNxooId7BGxeraK8qXvzKtw==",
             "dependencies": {
-                "browserslist": "^4.16.0",
+                "browserslist": "^4.16.6",
                 "caniuse-api": "^3.0.0"
             },
             "engines": {
@@ -7205,9 +7197,9 @@
             }
         },
         "node_modules/postcss-value-parser": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
-            "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+            "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
         },
         "node_modules/prettier": {
             "version": "2.5.0",
@@ -7299,25 +7291,25 @@
             "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
         },
         "node_modules/purgecss": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.0.3.tgz",
-            "integrity": "sha512-PYOIn5ibRIP34PBU9zohUcCI09c7drPJJtTDAc0Q6QlRz2/CHQ8ywGLdE7ZhxU2VTqB7p5wkvj5Qcm05Rz3Jmw==",
+            "version": "4.1.3",
+            "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz",
+            "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==",
             "dependencies": {
-                "commander": "^6.0.0",
-                "glob": "^7.0.0",
-                "postcss": "^8.2.1",
-                "postcss-selector-parser": "^6.0.2"
+                "commander": "^8.0.0",
+                "glob": "^7.1.7",
+                "postcss": "^8.3.5",
+                "postcss-selector-parser": "^6.0.6"
             },
             "bin": {
                 "purgecss": "bin/purgecss.js"
             }
         },
         "node_modules/purgecss/node_modules/commander": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
-            "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+            "version": "8.3.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+            "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
             "engines": {
-                "node": ">= 6"
+                "node": ">= 12"
             }
         },
         "node_modules/qs": {
@@ -8090,12 +8082,12 @@
             }
         },
         "node_modules/sockjs": {
-            "version": "0.3.21",
-            "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz",
-            "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==",
+            "version": "0.3.24",
+            "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+            "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
             "dependencies": {
                 "faye-websocket": "^0.11.3",
-                "uuid": "^3.4.0",
+                "uuid": "^8.3.2",
                 "websocket-driver": "^0.7.4"
             }
         },
@@ -8737,12 +8729,11 @@
             }
         },
         "node_modules/uuid": {
-            "version": "3.4.0",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-            "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
-            "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
+            "version": "8.3.2",
+            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
             "bin": {
-                "uuid": "bin/uuid"
+                "uuid": "dist/bin/uuid"
             }
         },
         "node_modules/v-clipboard": {
@@ -9349,28 +9340,28 @@
             }
         },
         "node_modules/yargs": {
-            "version": "17.2.1",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz",
-            "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==",
+            "version": "17.3.0",
+            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
+            "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
             "dependencies": {
                 "cliui": "^7.0.2",
                 "escalade": "^3.1.1",
                 "get-caller-file": "^2.0.5",
                 "require-directory": "^2.1.1",
-                "string-width": "^4.2.0",
+                "string-width": "^4.2.3",
                 "y18n": "^5.0.5",
-                "yargs-parser": "^20.2.2"
+                "yargs-parser": "^21.0.0"
             },
             "engines": {
                 "node": ">=12"
             }
         },
         "node_modules/yargs-parser": {
-            "version": "20.2.9",
-            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-            "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+            "version": "21.0.0",
+            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
+            "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
             "engines": {
-                "node": ">=10"
+                "node": ">=12"
             }
         }
     },
@@ -10438,9 +10429,9 @@
             }
         },
         "@discoveryjs/json-ext": {
-            "version": "0.5.5",
-            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz",
-            "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA=="
+            "version": "0.5.6",
+            "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz",
+            "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA=="
         },
         "@nodelib/fs.scandir": {
             "version": "2.1.5",
@@ -10466,9 +10457,9 @@
             }
         },
         "@popperjs/core": {
-            "version": "2.10.2",
-            "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz",
-            "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ=="
+            "version": "2.11.0",
+            "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.0.tgz",
+            "integrity": "sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ=="
         },
         "@trysound/sax": {
             "version": "0.2.0",
@@ -10620,9 +10611,9 @@
             "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
         },
         "@types/node": {
-            "version": "16.11.10",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.10.tgz",
-            "integrity": "sha512-3aRnHa1KlOEEhJ6+CvyHKK5vE9BcLGjtUpwvqYLRvYNQKMfabu3BwfJaA/SLW8dxe28LsNDjtHwePTuzn3gmOA=="
+            "version": "16.11.11",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
+            "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw=="
         },
         "@types/parse-json": {
             "version": "4.0.0",
@@ -11459,9 +11450,9 @@
             }
         },
         "caniuse-lite": {
-            "version": "1.0.30001283",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz",
-            "integrity": "sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg=="
+            "version": "1.0.30001284",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001284.tgz",
+            "integrity": "sha512-t28SKa7g6kiIQi6NHeOcKrOrGMzCRrXvlasPwWC26TH2QNdglgzQIRUuJ0cR3NeQPH+5jpuveeeSFDLm2zbkEw=="
         },
         "chalk": {
             "version": "4.1.2",
@@ -11576,9 +11567,9 @@
             }
         },
         "collect.js": {
-            "version": "4.29.0",
-            "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.29.0.tgz",
-            "integrity": "sha512-yhgGYEsLEcqnLT1NmRlN1+1euoz9SDhxQ4QyDhWYsKoWsg7252PKA5++dWaDs8mdFxbkmXDXQUaHXI9J2eTPkQ=="
+            "version": "4.29.3",
+            "resolved": "https://registry.npmjs.org/collect.js/-/collect.js-4.29.3.tgz",
+            "integrity": "sha512-/6idZ7r3B25Q4cForbiHJ7+aqupcgMEtrKRn9D3viCbLw+YuNFjd23HwDH89Y2cU4jlhkwksD80nZFKtNE25Gw=="
         },
         "color": {
             "version": "4.0.2",
@@ -11603,9 +11594,9 @@
             "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
         },
         "color-string": {
-            "version": "1.7.4",
-            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.7.4.tgz",
-            "integrity": "sha512-nVdUvPVgZMpRQad5dcsCMOSB5BXLljklTiaxS6ehhKxDsAI5sD7k5VmFuBt1y3Rlym8uulc/ANUN/bMWtBu6Sg==",
+            "version": "1.9.0",
+            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
+            "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
             "requires": {
                 "color-name": "^1.0.0",
                 "simple-swizzle": "^0.2.2"
@@ -11760,11 +11751,11 @@
             "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "core-js-compat": {
-            "version": "3.19.1",
-            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.1.tgz",
-            "integrity": "sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g==",
+            "version": "3.19.2",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.2.tgz",
+            "integrity": "sha512-ObBY1W5vx/LFFMaL1P5Udo4Npib6fu+cMokeziWkA8Tns4FcDemKF5j9JvaI5JhdkW8EQJQGJN1EcrzmEwuAqQ==",
             "requires": {
-                "browserslist": "^4.17.6",
+                "browserslist": "^4.18.1",
                 "semver": "7.0.0"
             },
             "dependencies": {
@@ -11917,9 +11908,9 @@
             },
             "dependencies": {
                 "domhandler": {
-                    "version": "4.2.2",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-                    "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -11958,20 +11949,20 @@
             "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
         },
         "cssnano": {
-            "version": "5.0.11",
-            "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.11.tgz",
-            "integrity": "sha512-5SHM31NAAe29jvy0MJqK40zZ/8dGlnlzcfHKw00bWMVFp8LWqtuyPSFwbaoIoxvt71KWJOfg8HMRGrBR3PExCg==",
+            "version": "5.0.12",
+            "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.12.tgz",
+            "integrity": "sha512-U38V4x2iJ3ijPdeWqUrEr4eKBB5PbEKsNP5T8xcik2Au3LeMtiMHX0i2Hu9k51FcKofNZumbrcdC6+a521IUHg==",
             "requires": {
-                "cssnano-preset-default": "^5.1.7",
+                "cssnano-preset-default": "^5.1.8",
                 "is-resolvable": "^1.1.0",
                 "lilconfig": "^2.0.3",
                 "yaml": "^1.10.2"
             }
         },
         "cssnano-preset-default": {
-            "version": "5.1.7",
-            "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.7.tgz",
-            "integrity": "sha512-bWDjtTY+BOqrqBtsSQIbN0RLGD2Yr2CnecpP0ydHNafh9ZUEre8c8VYTaH9FEbyOt0eIfEUAYYk5zj92ioO8LA==",
+            "version": "5.1.8",
+            "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.8.tgz",
+            "integrity": "sha512-zWMlP0+AMPBVE852SqTrP0DnhTcTA2C1wAF92TKZ3Va+aUVqLIhkqKlnJIXXdqXD7RN+S1ujuWmNpvrJBiM/vg==",
             "requires": {
                 "css-declaration-sorter": "^6.0.3",
                 "cssnano-utils": "^2.0.1",
@@ -11998,7 +11989,7 @@
                 "postcss-normalize-url": "^5.0.3",
                 "postcss-normalize-whitespace": "^5.0.1",
                 "postcss-ordered-values": "^5.0.2",
-                "postcss-reduce-initial": "^5.0.1",
+                "postcss-reduce-initial": "^5.0.2",
                 "postcss-reduce-transforms": "^5.0.1",
                 "postcss-svgo": "^5.0.3",
                 "postcss-unique-selectors": "^5.0.2"
@@ -12019,9 +12010,9 @@
             }
         },
         "date-fns": {
-            "version": "2.26.0",
-            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.26.0.tgz",
-            "integrity": "sha512-VQI812dRi3cusdY/fhoBKvc6l2W8BPWU1FNVnFH9Nttjx4AFBRzfSVb/Eyc7jBT6e9sg1XtAGsYpBQ6c/jygbg=="
+            "version": "2.27.0",
+            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.27.0.tgz",
+            "integrity": "sha512-sj+J0Mo2p2X1e306MHq282WS4/A8Pz/95GIFcsPNMPMZVI3EUrAdSv90al1k+p74WGLCruMXk23bfEDZa71X9Q=="
         },
         "dayjs": {
             "version": "1.10.7",
@@ -12034,9 +12025,9 @@
             "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0="
         },
         "debug": {
-            "version": "4.3.2",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
-            "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
+            "version": "4.3.3",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+            "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
             "requires": {
                 "ms": "2.1.2"
             }
@@ -12212,9 +12203,9 @@
             },
             "dependencies": {
                 "domhandler": {
-                    "version": "4.2.2",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-                    "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -12250,9 +12241,9 @@
             },
             "dependencies": {
                 "domhandler": {
-                    "version": "4.2.2",
-                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz",
-                    "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==",
+                    "version": "4.3.0",
+                    "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+                    "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
                     "requires": {
                         "domelementtype": "^2.2.0"
                     }
@@ -12284,9 +12275,9 @@
             "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "electron-to-chromium": {
-            "version": "1.4.3",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.3.tgz",
-            "integrity": "sha512-hfpppjYhqIZB8jrNb0rNceQRkSnBN7QJl3W26O1jUv3F3BkQknqy1YTqVXkFnIcFtBc3Qnv5M7r5Lez2iOLgZA=="
+            "version": "1.4.10",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.10.tgz",
+            "integrity": "sha512-tFgA40Iq2oy4k2PnZrLJowbgpij+lD6ZLxkw8Ht1NKTYyN8dvSvC5xlo8X0WW2jqhKSzITrbr5mpB4/AZ/8OUA=="
         },
         "elliptic": {
             "version": "6.5.4",
@@ -12983,9 +12974,9 @@
             }
         },
         "http-parser-js": {
-            "version": "0.5.3",
-            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz",
-            "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg=="
+            "version": "0.5.5",
+            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
+            "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA=="
         },
         "http-proxy": {
             "version": "1.18.1",
@@ -13364,9 +13355,9 @@
             "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
         },
         "jest-worker": {
-            "version": "27.3.1",
-            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz",
-            "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==",
+            "version": "27.4.2",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz",
+            "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==",
             "requires": {
                 "@types/node": "*",
                 "merge-stream": "^2.0.0",
@@ -13954,13 +13945,6 @@
                 "shellwords": "^0.1.1",
                 "uuid": "^8.3.0",
                 "which": "^2.0.2"
-            },
-            "dependencies": {
-                "uuid": {
-                    "version": "8.3.2",
-                    "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-                    "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
-                }
             }
         },
         "node-releases": {
@@ -14312,9 +14296,9 @@
             }
         },
         "postcss": {
-            "version": "8.4.1",
-            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.1.tgz",
-            "integrity": "sha512-WqLs/TTzXdG+/A4ZOOK9WDZiikrRaiA+eoEb/jz2DT9KUhMNHgP7yKPO8vwi62ZCsb703Gwb7BMZwDzI54Y2Ag==",
+            "version": "8.4.4",
+            "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.4.tgz",
+            "integrity": "sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q==",
             "requires": {
                 "nanoid": "^3.1.30",
                 "picocolors": "^1.0.0",
@@ -14403,12 +14387,12 @@
             }
         },
         "postcss-loader": {
-            "version": "6.2.0",
-            "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.0.tgz",
-            "integrity": "sha512-H9hv447QjQJVDbHj3OUdciyAXY3v5+UDduzEytAlZCVHCpNAAg/mCSwhYYqZr9BiGYhmYspU8QXxZwiHTLn3yA==",
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz",
+            "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==",
             "requires": {
                 "cosmiconfig": "^7.0.0",
-                "klona": "^2.0.4",
+                "klona": "^2.0.5",
                 "semver": "^7.3.5"
             }
         },
@@ -14596,11 +14580,11 @@
             }
         },
         "postcss-reduce-initial": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz",
-            "integrity": "sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw==",
+            "version": "5.0.2",
+            "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.2.tgz",
+            "integrity": "sha512-v/kbAAQ+S1V5v9TJvbGkV98V2ERPdU6XvMcKMjqAlYiJ2NtsHGlKYLPjWWcXlaTKNxooId7BGxeraK8qXvzKtw==",
             "requires": {
-                "browserslist": "^4.16.0",
+                "browserslist": "^4.16.6",
                 "caniuse-api": "^3.0.0"
             }
         },
@@ -14641,9 +14625,9 @@
             }
         },
         "postcss-value-parser": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
-            "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+            "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
         },
         "prettier": {
             "version": "2.5.0",
@@ -14718,20 +14702,20 @@
             "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
         },
         "purgecss": {
-            "version": "4.0.3",
-            "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.0.3.tgz",
-            "integrity": "sha512-PYOIn5ibRIP34PBU9zohUcCI09c7drPJJtTDAc0Q6QlRz2/CHQ8ywGLdE7ZhxU2VTqB7p5wkvj5Qcm05Rz3Jmw==",
+            "version": "4.1.3",
+            "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz",
+            "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==",
             "requires": {
-                "commander": "^6.0.0",
-                "glob": "^7.0.0",
-                "postcss": "^8.2.1",
-                "postcss-selector-parser": "^6.0.2"
+                "commander": "^8.0.0",
+                "glob": "^7.1.7",
+                "postcss": "^8.3.5",
+                "postcss-selector-parser": "^6.0.6"
             },
             "dependencies": {
                 "commander": {
-                    "version": "6.2.1",
-                    "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
-                    "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
+                    "version": "8.3.0",
+                    "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+                    "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
                 }
             }
         },
@@ -15342,12 +15326,12 @@
             }
         },
         "sockjs": {
-            "version": "0.3.21",
-            "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz",
-            "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==",
+            "version": "0.3.24",
+            "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+            "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
             "requires": {
                 "faye-websocket": "^0.11.3",
-                "uuid": "^3.4.0",
+                "uuid": "^8.3.2",
                 "websocket-driver": "^0.7.4"
             }
         },
@@ -15829,9 +15813,9 @@
             "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
         },
         "uuid": {
-            "version": "3.4.0",
-            "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-            "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+            "version": "8.3.2",
+            "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+            "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
         },
         "v-clipboard": {
             "version": "2.2.3",
@@ -16263,23 +16247,23 @@
             "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
         },
         "yargs": {
-            "version": "17.2.1",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz",
-            "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==",
+            "version": "17.3.0",
+            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz",
+            "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==",
             "requires": {
                 "cliui": "^7.0.2",
                 "escalade": "^3.1.1",
                 "get-caller-file": "^2.0.5",
                 "require-directory": "^2.1.1",
-                "string-width": "^4.2.0",
+                "string-width": "^4.2.3",
                 "y18n": "^5.0.5",
-                "yargs-parser": "^20.2.2"
+                "yargs-parser": "^21.0.0"
             }
         },
         "yargs-parser": {
-            "version": "20.2.9",
-            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-            "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="
+            "version": "21.0.0",
+            "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
+            "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA=="
         }
     }
 }

+ 2 - 27
resources/js/components/MoreOptions.vue

@@ -7,18 +7,7 @@
       id="project-options-menu-0"
       aria-has-popup="true"
       type="button"
-      class="
-        w-8
-        h-8
-        bg-white
-        inline-flex
-        items-center
-        justify-center
-        text-grey-400
-        rounded-full
-        hover:text-grey-500
-        focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500
-      "
+      class="w-8 h-8 bg-white inline-flex items-center justify-center text-grey-400 rounded-full hover:text-grey-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
     >
       <span class="sr-only">Open options</span>
 
@@ -39,21 +28,7 @@
     >
       <div
         v-show="isOpen"
-        class="
-          mx-3
-          origin-top-right
-          absolute
-          right-7
-          top-0
-          w-48
-          mt-1
-          rounded-md
-          shadow-lg
-          z-10
-          bg-white
-          ring-1 ring-black ring-opacity-5
-          divide-y divide-grey-200
-        "
+        class="mx-3 origin-top-right absolute right-7 top-0 w-48 mt-1 rounded-md shadow-lg z-10 bg-white ring-1 ring-black ring-opacity-5 divide-y divide-grey-200"
         role="menu"
         aria-orientation="vertical"
         aria-labelledby="project-options-menu-0"

+ 2 - 28
resources/js/components/Toggle.vue

@@ -4,38 +4,12 @@
     type="button"
     :aria-pressed="value.toString()"
     :class="this.value ? 'bg-cyan-500' : 'bg-grey-300'"
-    class="
-      relative
-      inline-flex
-      flex-shrink-0
-      h-6
-      w-11
-      border-2 border-transparent
-      rounded-full
-      cursor-pointer
-      transition-colors
-      ease-in-out
-      duration-200
-      focus:outline-none
-    "
+    class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none"
   >
     <span class="sr-only">Use setting</span>
     <span
       :class="this.value ? 'translate-x-5' : 'translate-x-0'"
-      class="
-        relative
-        inline-block
-        h-5
-        w-5
-        rounded-full
-        bg-white
-        shadow
-        transform
-        ring-0
-        transition
-        ease-in-out
-        duration-200
-      "
+      class="relative inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"
     >
       <span
         :class="this.value ? 'opacity-0 ease-out duration-100' : 'opacity-100 ease-in duration-200'"

+ 2 - 22
resources/js/components/WebauthnKeys.vue

@@ -59,16 +59,7 @@
         <div class="mt-6">
           <button
             @click="remove"
-            class="
-              bg-red-500
-              hover:bg-red-600
-              text-white
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-red-500 hover:bg-red-600 text-white font-bold py-3 px-4 rounded focus:outline-none"
             :class="removeKeyLoading ? 'cursor-not-allowed' : ''"
             :disabled="removeKeyLoading"
           >
@@ -77,18 +68,7 @@
           </button>
           <button
             @click="closeDeleteKeyModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Close
           </button>

+ 9 - 99
resources/js/components/passport/PersonalAccessTokens.vue

@@ -36,17 +36,7 @@
 
     <button
       @click="openCreateTokenModal"
-      class="
-        bg-cyan-400
-        w-full
-        hover:bg-cyan-300
-        text-cyan-900
-        font-bold
-        py-3
-        px-4
-        rounded
-        focus:outline-none
-      "
+      class="bg-cyan-400 w-full hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
     >
       Generate New Token
     </button>
@@ -117,33 +107,14 @@
             v-model="form.name"
             type="text"
             id="create-token-name"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-              mb-6
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 mb-6"
             :class="form.errors.length > 0 ? 'border-red-500' : ''"
             placeholder="e.g. Firefox extension"
             autofocus
           />
           <button
             @click="store"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="loading ? 'cursor-not-allowed' : ''"
             :disabled="loading"
           >
@@ -152,18 +123,7 @@
           </button>
           <button
             @click="closeCreateTokenModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Close
           </button>
@@ -181,33 +141,14 @@
         </p>
         <textarea
           v-model="accessToken"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-3
-            text-sm
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 text-sm"
           rows="10"
           readonly
         >
         </textarea>
         <div class="mt-6">
           <button
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             v-clipboard="() => accessToken"
             v-clipboard:success="clipboardSuccess"
             v-clipboard:error="clipboardError"
@@ -216,18 +157,7 @@
           </button>
           <button
             @click="closeCreateTokenModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Close
           </button>
@@ -249,16 +179,7 @@
         <div class="mt-6">
           <button
             @click="revoke"
-            class="
-              bg-red-500
-              hover:bg-red-600
-              text-white
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-red-500 hover:bg-red-600 text-white font-bold py-3 px-4 rounded focus:outline-none"
             :class="revokeTokenLoading ? 'cursor-not-allowed' : ''"
             :disabled="revokeTokenLoading"
           >
@@ -267,18 +188,7 @@
           </button>
           <button
             @click="closeRevokeTokenModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Close
           </button>

+ 42 - 485
resources/js/pages/Aliases.vue

@@ -2,21 +2,7 @@
   <div class="aliases">
     <div class="flex flex-wrap flex-row items-center justify-between mb-8 md:px-2 lg:px-6">
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-          mb-4
-          lg:mb-4
-          xl:mb-0
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white mb-4 lg:mb-4 xl:mb-0"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -30,21 +16,7 @@
         </div>
       </div>
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-          mb-4
-          lg:mb-4
-          xl:mb-0
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white mb-4 lg:mb-4 xl:mb-0"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -58,21 +30,7 @@
         </div>
       </div>
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-          mb-4
-          lg:mb-4
-          xl:mb-0
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white mb-4 lg:mb-4 xl:mb-0"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -86,20 +44,7 @@
         </div>
       </div>
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-          mb-4
-          lg:mb-0
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white mb-4 lg:mb-0"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -113,20 +58,7 @@
         </div>
       </div>
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-          mb-4
-          md:mb-0
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white mb-4 md:mb-0"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -140,18 +72,7 @@
         </div>
       </div>
       <div
-        class="
-          w-full
-          md:w-1/2
-          lg:w-1/3
-          xl:w-1/6
-          md:-mx-2
-          lg:-mx-6
-          rounded
-          overflow-hidden
-          shadow-md
-          bg-white
-        "
+        class="w-full md:w-1/2 lg:w-1/3 xl:w-1/6 md:-mx-2 lg:-mx-6 rounded overflow-hidden shadow-md bg-white"
       >
         <div class="p-4 flex items-center justify-between relative">
           <icon
@@ -172,73 +93,26 @@
           @keyup.esc="search = ''"
           tabindex="0"
           type="text"
-          class="
-            w-full
-            md:w-64
-            appearance-none
-            shadow
-            bg-white
-            text-grey-700
-            focus:outline-none
-            rounded
-            py-3
-            pl-3
-            pr-8
-          "
+          class="w-full md:w-64 appearance-none shadow bg-white text-grey-700 focus:outline-none rounded py-3 pl-3 pr-8"
           placeholder="Search Aliases"
         />
         <icon
           v-if="search"
           @click.native="search = ''"
           name="close-circle"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            mr-2
-            flex
-            items-center
-            cursor-pointer
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current mr-2 flex items-center cursor-pointer"
         />
         <icon
           v-else
           name="search"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            pointer-events-none
-            mr-2
-            flex
-            items-center
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
         />
       </div>
       <div class="flex flex-wrap mt-4 md:mt-0">
         <div class="block relative mr-4">
           <select
             v-model="showAliases"
-            class="
-              block
-              appearance-none
-              w-full
-              text-grey-700
-              bg-white
-              p-3
-              pr-8
-              rounded
-              shadow
-              focus:ring
-            "
+            class="block appearance-none w-full text-grey-700 bg-white p-3 pr-8 rounded shadow focus:ring"
             required
           >
             <option value="without">Hide Deleted</option>
@@ -246,16 +120,7 @@
             <option value="only">Deleted Only</option>
           </select>
           <div
-            class="
-              pointer-events-none
-              absolute
-              inset-y-0
-              right-0
-              flex
-              items-center
-              px-2
-              text-gray-700
-            "
+            class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
           >
             <svg
               class="fill-current h-4 w-4"
@@ -271,17 +136,7 @@
         <div>
           <button
             @click="generateAliasModalOpen = true"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-              ml-auto
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
           >
             Create New Alias
           </button>
@@ -356,18 +211,7 @@
               @keyup.esc="aliasIdToEdit = aliasDescriptionToEdit = ''"
               v-model="aliasDescriptionToEdit"
               type="text"
-              class="
-                flex-grow
-                text-sm
-                appearance-none
-                bg-grey-100
-                border
-                text-grey-700
-                focus:outline-none
-                rounded
-                px-2
-                py-1
-              "
+              class="flex-grow text-sm appearance-none bg-grey-100 border text-grey-700 focus:outline-none rounded px-2 py-1"
               :class="aliasDescriptionToEdit.length > 200 ? 'border-red-500' : 'border-transparent'"
               placeholder="Add description"
               tabindex="0"
@@ -398,13 +242,7 @@
           </div>
           <div v-else>
             <span
-              class="
-                inline-block
-                text-grey-300 text-sm
-                cursor-pointer
-                py-1
-                border border-transparent
-              "
+              class="inline-block text-grey-300 text-sm cursor-pointer py-1 border border-transparent"
               @click=";(aliasIdToEdit = props.row.id), (aliasDescriptionToEdit = '')"
               >Add description</span
             >
@@ -426,16 +264,7 @@
           }}</span>
           <span
             v-else-if="has(props.row.aliasable, 'default_recipient.email')"
-            class="
-              py-1
-              px-2
-              text-xs
-              bg-yellow-200
-              text-yellow-900
-              rounded-full
-              tooltip
-              outline-none
-            "
+            class="py-1 px-2 text-xs bg-yellow-200 text-yellow-900 rounded-full tooltip outline-none"
             :data-tippy-content="props.row.aliasable.default_recipient.email"
             >{{
               props.row.aliasable_type === 'App\\Models\\Domain' ? 'domain' : 'username'
@@ -443,16 +272,7 @@
           >
           <span
             v-else
-            class="
-              py-1
-              px-2
-              text-xs
-              bg-yellow-200
-              text-yellow-900
-              rounded-full
-              tooltip
-              outline-none
-            "
+            class="py-1 px-2 text-xs bg-yellow-200 text-yellow-900 rounded-full tooltip outline-none"
             :data-tippy-content="defaultRecipientEmail"
             >default</span
           >
@@ -493,16 +313,7 @@
             <div role="none">
               <span
                 @click="openSendFromModal(props.row)"
-                class="
-                  group
-                  cursor-pointer
-                  flex
-                  items-center
-                  px-4
-                  py-3
-                  text-sm text-grey-700
-                  hover:bg-grey-100 hover:text-grey-900
-                "
+                class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
                 role="menuitem"
               >
                 <icon name="send" class="block mr-3 w-5 h-5 text-grey-300 outline-none" />
@@ -512,16 +323,7 @@
             <div v-if="props.row.deleted_at" role="none">
               <span
                 @click="openRestoreModal(props.row.id)"
-                class="
-                  group
-                  cursor-pointer
-                  flex
-                  items-center
-                  px-4
-                  py-3
-                  text-sm text-grey-700
-                  hover:bg-grey-100 hover:text-grey-900
-                "
+                class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
                 role="menuitem"
               >
                 <icon
@@ -534,16 +336,7 @@
             <div v-else role="none">
               <span
                 @click="openDeleteModal(props.row)"
-                class="
-                  group
-                  cursor-pointer
-                  flex
-                  items-center
-                  px-4
-                  py-3
-                  text-sm text-grey-700
-                  hover:bg-grey-100 hover:text-grey-900
-                "
+                class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
                 role="menuitem"
               >
                 <icon
@@ -556,16 +349,7 @@
             <div role="none">
               <span
                 @click="openForgetModal(props.row)"
-                class="
-                  group
-                  cursor-pointer
-                  flex
-                  items-center
-                  px-4
-                  py-3
-                  text-sm text-grey-700
-                  hover:bg-grey-100 hover:text-grey-900
-                "
+                class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
                 role="menuitem"
               >
                 <icon
@@ -642,18 +426,7 @@
           <select
             v-model="generateAliasDomain"
             id="alias_domain"
-            class="
-              block
-              appearance-none
-              w-full
-              text-grey-700
-              bg-grey-100
-              p-3
-              pr-8
-              rounded
-              shadow
-              focus:ring
-            "
+            class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring"
             required
           >
             <option v-for="domainOption in domainOptions" :key="domainOption" :value="domainOption">
@@ -661,16 +434,7 @@
             </option>
           </select>
           <div
-            class="
-              pointer-events-none
-              absolute
-              inset-y-0
-              right-0
-              flex
-              items-center
-              px-2
-              text-gray-700
-            "
+            class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
           >
             <svg
               class="fill-current h-4 w-4"
@@ -691,18 +455,7 @@
           <select
             v-model="generateAliasFormat"
             id="alias_format"
-            class="
-              block
-              appearance-none
-              w-full
-              text-grey-700
-              bg-grey-100
-              p-3
-              pr-8
-              rounded
-              shadow
-              focus:ring
-            "
+            class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring"
             required
           >
             <option
@@ -714,16 +467,7 @@
             </option>
           </select>
           <div
-            class="
-              pointer-events-none
-              absolute
-              inset-y-0
-              right-0
-              flex
-              items-center
-              px-2
-              text-gray-700
-            "
+            class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
           >
             <svg
               class="fill-current h-4 w-4"
@@ -748,16 +492,7 @@
             v-model="generateAliasLocalPart"
             id="alias_local_part"
             type="text"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
             :class="errors.generateAliasLocalPart ? 'border-red-500' : ''"
             placeholder="Enter local part..."
             autofocus
@@ -774,16 +509,7 @@
           v-model="generateAliasDescription"
           id="alias_description"
           type="text"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-3
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
           :class="errors.generateAliasDescription ? 'border-red-500' : ''"
           placeholder="Enter description (optional)..."
           autofocus
@@ -815,16 +541,7 @@
         <div class="mt-6">
           <button
             @click="generateNewAlias"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="generateAliasLoading ? 'cursor-not-allowed' : ''"
             :disabled="generateAliasLoading"
           >
@@ -833,18 +550,7 @@
           </button>
           <button
             @click="generateAliasModalOpen = false"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -882,17 +588,7 @@
           <button
             type="button"
             @click="editAliasRecipients()"
-            class="
-              px-4
-              py-3
-              text-cyan-900
-              font-semibold
-              bg-cyan-400
-              hover:bg-cyan-300
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
             :class="editAliasRecipientsLoading ? 'cursor-not-allowed' : ''"
             :disabled="editAliasRecipientsLoading"
           >
@@ -901,18 +597,7 @@
           </button>
           <button
             @click="closeAliasRecipientsModal()"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -935,17 +620,7 @@
           <button
             type="button"
             @click="restoreAlias(aliasIdToRestore)"
-            class="
-              px-4
-              py-3
-              text-cyan-900
-              font-semibold
-              bg-cyan-400
-              hover:bg-cyan-300
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
             :class="restoreAliasLoading ? 'cursor-not-allowed' : ''"
             :disabled="restoreAliasLoading"
           >
@@ -954,18 +629,7 @@
           </button>
           <button
             @click="closeRestoreModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -990,17 +654,7 @@
           <button
             type="button"
             @click="deleteAlias(aliasToDelete.id)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteAliasLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteAliasLoading"
           >
@@ -1009,18 +663,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -1048,17 +691,7 @@
           <button
             type="button"
             @click="forgetAlias(aliasToForget.id)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="forgetAliasLoading ? 'cursor-not-allowed' : ''"
             :disabled="forgetAliasLoading"
           >
@@ -1067,18 +700,7 @@
           </button>
           <button
             @click="closeForgetModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -1102,16 +724,7 @@
           v-model="aliasToSendFrom.email"
           id="send_from_alias"
           type="text"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-3
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
           disabled
         />
         <label for="send_from_alias_destination" class="block text-grey-700 text-sm my-2">
@@ -1124,16 +737,7 @@
           v-model="sendFromAliasDestination"
           id="send_from_alias_destination"
           type="text"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-3
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
           :class="errors.sendFromAliasDestination ? 'border-red-500' : ''"
           placeholder="Enter email..."
           autofocus
@@ -1145,20 +749,7 @@
           <div
             v-clipboard="() => sendFromAliasEmailToSendTo"
             v-clipboard:success="setSendFromAliasCopied"
-            class="
-              flex
-              items-center
-              justify-between
-              cursor-pointer
-              text-xs
-              border-t-4
-              rounded-sm
-              text-green-800
-              border-green-600
-              bg-green-100
-              p-2
-              mb-3
-            "
+            class="flex items-center justify-between cursor-pointer text-xs border-t-4 rounded-sm text-green-800 border-green-600 bg-green-100 p-2 mb-3"
             role="alert"
           >
             <span>
@@ -1195,20 +786,7 @@
           </div>
           <a
             :href="'mailto:' + sendFromAliasEmailToSendTo"
-            class="
-              flex
-              items-center
-              justify-between
-              cursor-pointer
-              text-sm
-              border-t-4
-              rounded-sm
-              text-green-800
-              border-green-600
-              bg-green-100
-              p-2
-              mb-4
-            "
+            class="flex items-center justify-between cursor-pointer text-sm border-t-4 rounded-sm text-green-800 border-green-600 bg-green-100 p-2 mb-4"
             role="alert"
             title="Click To Open Mail Application"
           >
@@ -1219,17 +797,7 @@
           <button
             type="button"
             @click="displaySendFromAddress(aliasToSendFrom)"
-            class="
-              px-4
-              py-3
-              text-cyan-900
-              font-semibold
-              bg-cyan-400
-              hover:bg-cyan-300
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
             :class="sendFromAliasLoading ? 'cursor-not-allowed' : ''"
             :disabled="sendFromAliasLoading"
           >
@@ -1238,18 +806,7 @@
           </button>
           <button
             @click="closeSendFromModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Close
           </button>

+ 14 - 162
resources/js/pages/Domains.vue

@@ -7,71 +7,25 @@
           @keyup.esc="search = ''"
           tabindex="0"
           type="text"
-          class="
-            w-full
-            md:w-64
-            appearance-none
-            shadow
-            bg-white
-            text-grey-700
-            focus:outline-none
-            rounded
-            py-3
-            pl-3
-            pr-8
-          "
+          class="w-full md:w-64 appearance-none shadow bg-white text-grey-700 focus:outline-none rounded py-3 pl-3 pr-8"
           placeholder="Search Domains"
         />
         <icon
           v-if="search"
           @click.native="search = ''"
           name="close-circle"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            mr-2
-            flex
-            items-center
-            cursor-pointer
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current mr-2 flex items-center cursor-pointer"
         />
         <icon
           v-else
           name="search"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            pointer-events-none
-            mr-2
-            flex
-            items-center
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
         />
       </div>
       <div class="mt-4 md:mt-0">
         <button
           @click="addDomainModalOpen = true"
-          class="
-            bg-cyan-400
-            hover:bg-cyan-300
-            text-cyan-900
-            font-bold
-            py-3
-            px-4
-            rounded
-            focus:outline-none
-            ml-auto
-          "
+          class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
         >
           Add Custom Domain
         </button>
@@ -121,17 +75,7 @@
               @keyup.esc="domainIdToEdit = domainDescriptionToEdit = ''"
               v-model="domainDescriptionToEdit"
               type="text"
-              class="
-                flex-grow
-                appearance-none
-                bg-grey-100
-                border
-                text-grey-700
-                focus:outline-none
-                rounded
-                px-2
-                py-1
-              "
+              class="flex-grow appearance-none bg-grey-100 border text-grey-700 focus:outline-none rounded px-2 py-1"
               :class="
                 domainDescriptionToEdit.length > 200 ? 'border-red-500' : 'border-transparent'
               "
@@ -354,33 +298,14 @@
           <input
             v-model="newDomain"
             type="text"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-              mb-6
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 mb-6"
             :class="errors.newDomain ? 'border-red-500' : ''"
             placeholder="example.com"
             autofocus
           />
           <button
             @click="validateNewDomain"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="addDomainLoading ? 'cursor-not-allowed' : ''"
             :disabled="addDomainLoading"
           >
@@ -389,18 +314,7 @@
           </button>
           <button
             @click="addDomainModalOpen = false"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -446,16 +360,7 @@
         <div class="mt-6">
           <button
             @click="checkRecords(domainToCheck)"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="checkRecordsLoading ? 'cursor-not-allowed' : ''"
             :disabled="checkRecordsLoading"
           >
@@ -464,18 +369,7 @@
           </button>
           <button
             @click="closeCheckRecordsModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -514,17 +408,7 @@
           <button
             type="button"
             @click="editDefaultRecipient()"
-            class="
-              px-4
-              py-3
-              text-cyan-900
-              font-semibold
-              bg-cyan-400
-              hover:bg-cyan-300
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
             :class="editDefaultRecipientLoading ? 'cursor-not-allowed' : ''"
             :disabled="editDefaultRecipientLoading"
           >
@@ -533,18 +417,7 @@
           </button>
           <button
             @click="closeDomainDefaultRecipientModal()"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -567,17 +440,7 @@
           <button
             type="button"
             @click="deleteDomain(domainIdToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteDomainLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteDomainLoading"
           >
@@ -586,18 +449,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>

+ 5 - 62
resources/js/pages/FailedDeliveries.vue

@@ -7,55 +7,19 @@
           @keyup.esc="search = ''"
           tabindex="0"
           type="text"
-          class="
-            w-full
-            md:w-64
-            appearance-none
-            shadow
-            bg-white
-            text-grey-700
-            focus:outline-none
-            rounded
-            py-3
-            pl-3
-            pr-8
-          "
+          class="w-full md:w-64 appearance-none shadow bg-white text-grey-700 focus:outline-none rounded py-3 pl-3 pr-8"
           placeholder="Search Failed Deliveries"
         />
         <icon
           v-if="search"
           @click.native="search = ''"
           name="close-circle"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            mr-2
-            flex
-            items-center
-            cursor-pointer
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current mr-2 flex items-center cursor-pointer"
         />
         <icon
           v-else
           name="search"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            pointer-events-none
-            mr-2
-            flex
-            items-center
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
         />
       </div>
     </div>
@@ -187,17 +151,7 @@
           <button
             type="button"
             @click="deleteFailedDelivery(failedDeliveryIdToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteFailedDeliveryLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteFailedDeliveryLoading"
           >
@@ -206,18 +160,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>

+ 15 - 173
resources/js/pages/Recipients.vue

@@ -7,71 +7,25 @@
           @keyup.esc="search = ''"
           tabindex="0"
           type="text"
-          class="
-            w-full
-            md:w-64
-            appearance-none
-            shadow
-            bg-white
-            text-grey-700
-            focus:outline-none
-            rounded
-            py-3
-            pl-3
-            pr-8
-          "
+          class="w-full md:w-64 appearance-none shadow bg-white text-grey-700 focus:outline-none rounded py-3 pl-3 pr-8"
           placeholder="Search Recipients"
         />
         <icon
           v-if="search"
           @click.native="search = ''"
           name="close-circle"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            mr-2
-            flex
-            items-center
-            cursor-pointer
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current mr-2 flex items-center cursor-pointer"
         />
         <icon
           v-else
           name="search"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            pointer-events-none
-            mr-2
-            flex
-            items-center
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
         />
       </div>
       <div class="mt-4 md:mt-0">
         <button
           @click="addRecipientModalOpen = true"
-          class="
-            bg-cyan-400
-            hover:bg-cyan-300
-            text-cyan-900
-            font-bold
-            py-3
-            px-4
-            rounded
-            focus:outline-none
-            ml-auto
-          "
+          class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
         >
           Add Recipient
         </button>
@@ -165,17 +119,7 @@
             />
             <icon
               name="fingerprint"
-              class="
-                tooltip
-                outline-none
-                cursor-pointer
-                block
-                w-6
-                h-6
-                text-grey-300
-                fill-current
-                mx-2
-              "
+              class="tooltip outline-none cursor-pointer block w-6 h-6 text-grey-300 fill-current mx-2"
               :data-tippy-content="props.row.fingerprint"
               v-clipboard="() => props.row.fingerprint"
               v-clipboard:success="clipboardSuccess"
@@ -246,33 +190,14 @@
           <input
             v-model="newRecipient"
             type="email"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-              mb-6
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 mb-6"
             :class="errors.newRecipient ? 'border-red-500' : ''"
             placeholder="johndoe@example.com"
             autofocus
           />
           <button
             @click="validateNewRecipient"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="addRecipientLoading ? 'cursor-not-allowed' : ''"
             :disabled="addRecipientLoading"
           >
@@ -281,18 +206,7 @@
           </button>
           <button
             @click="addRecipientModalOpen = false"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -315,17 +229,7 @@
           </p>
           <textarea
             v-model="recipientKey"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-              mb-6
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 mb-6"
             :class="errors.recipientKey ? 'border-red-500' : ''"
             placeholder="Begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'"
             rows="10"
@@ -335,16 +239,7 @@
           <button
             type="button"
             @click="validateRecipientKey"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="addRecipientKeyLoading ? 'cursor-not-allowed' : ''"
             :disabled="addRecipientKeyLoading"
           >
@@ -353,18 +248,7 @@
           </button>
           <button
             @click="closeRecipientKeyModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -387,17 +271,7 @@
           <button
             type="button"
             @click="deleteRecipientKey(recipientKeyToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteRecipientKeyLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteRecipientKeyLoading"
           >
@@ -406,18 +280,7 @@
           </button>
           <button
             @click="closeDeleteRecipientKeyModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -437,17 +300,7 @@
           <button
             type="button"
             @click="deleteRecipient(recipientToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteRecipientLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteRecipientLoading"
           >
@@ -456,18 +309,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>

+ 134 - 408
resources/js/pages/Rules.vue

@@ -7,17 +7,7 @@
       </div>
       <button
         @click="openCreateModal"
-        class="
-          bg-cyan-400
-          hover:bg-cyan-300
-          text-cyan-900
-          font-bold
-          py-3
-          px-4
-          rounded
-          focus:outline-none
-          ml-auto
-        "
+        class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
       >
         Add New Rule
       </button>
@@ -110,16 +100,7 @@
           v-model="createRuleObject.name"
           id="rule_name"
           type="text"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-2
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-2"
           :class="errors.ruleName ? 'border-red-500' : ''"
           placeholder="Enter name"
           autofocus
@@ -136,34 +117,14 @@
                 <select
                   v-model="createRuleObject.operator"
                   id="rule_operator"
-                  class="
-                    block
-                    appearance-none
-                    w-full
-                    text-grey-700
-                    bg-white
-                    p-2
-                    pr-6
-                    rounded
-                    shadow
-                    focus:ring
-                  "
+                  class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                   required
                 >
                   <option value="AND">AND</option>
                   <option value="OR">OR</option>
                 </select>
                 <div
-                  class="
-                    pointer-events-none
-                    absolute
-                    inset-y-0
-                    right-0
-                    flex
-                    items-center
-                    px-2
-                    text-gray-700
-                  "
+                  class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                 >
                   <svg
                     class="fill-current h-4 w-4"
@@ -187,18 +148,7 @@
                       <select
                         v-model="createRuleObject.conditions[key].type"
                         id="rule_condition_types"
-                        class="
-                          block
-                          appearance-none
-                          w-32
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -210,16 +160,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -242,18 +183,7 @@
                       <select
                         v-model="createRuleObject.conditions[key].match"
                         id="rule_condition_matches"
-                        class="
-                          block
-                          appearance-none
-                          w-40
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -265,16 +195,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -293,26 +214,16 @@
                         v-model="createRuleObject.conditions[key].currentConditionValue"
                         @keyup.enter="addValueToCondition(createRuleObject, key)"
                         type="text"
-                        class="
-                          w-full
-                          appearance-none
-                          bg-white
-                          border border-transparent
-                          rounded-l
-                          text-grey-700
-                          focus:outline-none
-                          p-2
-                        "
+                        class="w-full appearance-none bg-white border border-transparent rounded-l text-grey-700 focus:outline-none p-2"
                         :class="errors.createRuleValues ? 'border-red-500' : ''"
                         placeholder="Enter value"
                         autofocus
                       />
-                      <button class="p-2 bg-grey-200 rounded-r text-grey-600">
-                        <icon
-                          name="check"
-                          class="block w-6 h-6 text-grey-600 fill-current cursor-pointer"
-                          @click.native="addValueToCondition(createRuleObject, key)"
-                        />
+                      <button
+                        @click="addValueToCondition(createRuleObject, key)"
+                        class="p-2 bg-grey-200 rounded-r text-grey-600"
+                      >
+                        Insert
                       </button>
                     </div>
                   </span>
@@ -353,16 +264,7 @@
           <!-- add condition button -->
           <button
             @click="addCondition(createRuleObject)"
-            class="
-              mt-4
-              p-2
-              text-grey-800
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="mt-4 p-2 text-grey-800 bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Add condition
           </button>
@@ -392,17 +294,7 @@
                         v-model="createRuleObject.actions[key].type"
                         @change="ruleActionChange(createRuleObject.actions[key])"
                         id="rule_action_types"
-                        class="
-                          block
-                          appearance-none
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -414,16 +306,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -449,16 +332,7 @@
                       <input
                         v-model="createRuleObject.actions[key].value"
                         type="text"
-                        class="
-                          w-full
-                          appearance-none
-                          bg-white
-                          border border-transparent
-                          rounded
-                          text-grey-700
-                          focus:outline-none
-                          p-2
-                        "
+                        class="w-full appearance-none bg-white border border-transparent rounded text-grey-700 focus:outline-none p-2"
                         :class="errors.createRuleActionValue ? 'border-red-500' : ''"
                         placeholder="Enter value"
                         autofocus
@@ -474,18 +348,7 @@
                       <select
                         v-model="createRuleObject.actions[key].value"
                         id="create_rule_action_banner"
-                        class="
-                          block
-                          appearance-none
-                          w-40
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option selected value="top">Top</option>
@@ -493,16 +356,7 @@
                         <option selected value="off">Off</option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -532,16 +386,7 @@
           <!-- add action button -->
           <button
             @click="addAction(createRuleObject)"
-            class="
-              mt-4
-              p-2
-              text-grey-800
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="mt-4 p-2 text-grey-800 bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Add action
           </button>
@@ -551,19 +396,46 @@
           </p>
         </fieldset>
 
+        <fieldset class="border border-cyan-400 p-4 my-4 rounded-sm">
+          <legend class="px-2 leading-none text-sm">Run rule on</legend>
+          <div class="w-full flex">
+            <div class="relative flex items-center">
+              <input
+                v-model="createRuleObject.forwards"
+                id="forwards"
+                name="forwards"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="forwards" class="ml-2 text-sm text-grey-700">Forwards</label>
+            </div>
+            <div class="relative flex items-center mx-4">
+              <input
+                v-model="createRuleObject.replies"
+                id="replies"
+                name="replies"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="replies" class="ml-2 text-sm text-grey-700">Replies</label>
+            </div>
+            <div class="relative flex items-center">
+              <input
+                v-model="createRuleObject.sends"
+                id="sends"
+                name="sends"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="sends" class="ml-2 text-sm text-grey-700">Sends</label>
+            </div>
+          </div>
+        </fieldset>
+
         <div class="mt-6">
           <button
             @click="createNewRule"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="createRuleLoading ? 'cursor-not-allowed' : ''"
             :disabled="createRuleLoading"
           >
@@ -572,18 +444,7 @@
           </button>
           <button
             @click="createRuleModalOpen = false"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -611,16 +472,7 @@
           v-model="editRuleObject.name"
           id="edit_rule_name"
           type="text"
-          class="
-            w-full
-            appearance-none
-            bg-grey-100
-            border border-transparent
-            text-grey-700
-            focus:outline-none
-            rounded
-            p-2
-          "
+          class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-2"
           :class="errors.ruleName ? 'border-red-500' : ''"
           placeholder="Enter name"
           autofocus
@@ -637,34 +489,14 @@
                 <select
                   v-model="editRuleObject.operator"
                   id="edit_rule_operator"
-                  class="
-                    block
-                    appearance-none
-                    w-full
-                    text-grey-700
-                    bg-white
-                    p-2
-                    pr-6
-                    rounded
-                    shadow
-                    focus:ring
-                  "
+                  class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                   required
                 >
                   <option value="AND">AND</option>
                   <option value="OR">OR</option>
                 </select>
                 <div
-                  class="
-                    pointer-events-none
-                    absolute
-                    inset-y-0
-                    right-0
-                    flex
-                    items-center
-                    px-2
-                    text-gray-700
-                  "
+                  class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                 >
                   <svg
                     class="fill-current h-4 w-4"
@@ -688,18 +520,7 @@
                       <select
                         v-model="editRuleObject.conditions[key].type"
                         id="edit_rule_condition_types"
-                        class="
-                          block
-                          appearance-none
-                          w-32
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -711,16 +532,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -740,18 +552,7 @@
                       <select
                         v-model="editRuleObject.conditions[key].match"
                         id="edit_rule_condition_matches"
-                        class="
-                          block
-                          appearance-none
-                          w-40
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -763,16 +564,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -791,26 +583,16 @@
                         v-model="editRuleObject.conditions[key].currentConditionValue"
                         @keyup.enter="addValueToCondition(editRuleObect, key)"
                         type="text"
-                        class="
-                          w-full
-                          appearance-none
-                          bg-white
-                          border border-transparent
-                          rounded-l
-                          text-grey-700
-                          focus:outline-none
-                          p-2
-                        "
+                        class="w-full appearance-none bg-white border border-transparent rounded-l text-grey-700 focus:outline-none p-2"
                         :class="errors.ruleConditions ? 'border-red-500' : ''"
                         placeholder="Enter value"
                         autofocus
                       />
-                      <button class="p-2 bg-grey-200 rounded-r text-grey-600">
-                        <icon
-                          name="check"
-                          class="block w-6 h-6 text-grey-600 fill-current cursor-pointer"
-                          @click.native="addValueToCondition(editRuleObject, key)"
-                        />
+                      <button
+                        @click="addValueToCondition(editRuleObject, key)"
+                        class="p-2 bg-grey-200 rounded-r text-grey-600"
+                      >
+                        Insert
                       </button>
                     </div>
                   </span>
@@ -848,16 +630,7 @@
           <!-- add condition button -->
           <button
             @click="addCondition(editRuleObject)"
-            class="
-              mt-4
-              p-2
-              text-grey-800
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="mt-4 p-2 text-grey-800 bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Add condition
           </button>
@@ -887,17 +660,7 @@
                         v-model="editRuleObject.actions[key].type"
                         @change="ruleActionChange(editRuleObject.actions[key])"
                         id="rule_action_types"
-                        class="
-                          block
-                          appearance-none
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option
@@ -909,16 +672,7 @@
                         </option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -944,16 +698,7 @@
                       <input
                         v-model="editRuleObject.actions[key].value"
                         type="text"
-                        class="
-                          w-full
-                          appearance-none
-                          bg-white
-                          border border-transparent
-                          rounded
-                          text-grey-700
-                          focus:outline-none
-                          p-2
-                        "
+                        class="w-full appearance-none bg-white border border-transparent rounded text-grey-700 focus:outline-none p-2"
                         :class="errors.ruleActions ? 'border-red-500' : ''"
                         placeholder="Enter value"
                         autofocus
@@ -966,18 +711,7 @@
                       <select
                         v-model="editRuleObject.actions[key].value"
                         id="edit_rule_action_banner"
-                        class="
-                          block
-                          appearance-none
-                          w-40
-                          text-grey-700
-                          bg-white
-                          p-2
-                          pr-6
-                          rounded
-                          shadow
-                          focus:ring
-                        "
+                        class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
                         required
                       >
                         <option value="top">Top</option>
@@ -985,16 +719,7 @@
                         <option value="off">Off</option>
                       </select>
                       <div
-                        class="
-                          pointer-events-none
-                          absolute
-                          inset-y-0
-                          right-0
-                          flex
-                          items-center
-                          px-2
-                          text-gray-700
-                        "
+                        class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
                       >
                         <svg
                           class="fill-current h-4 w-4"
@@ -1024,16 +749,7 @@
           <!-- add action button -->
           <button
             @click="addAction(editRuleObject)"
-            class="
-              mt-4
-              p-2
-              text-grey-800
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="mt-4 p-2 text-grey-800 bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Add action
           </button>
@@ -1043,19 +759,46 @@
           </p>
         </fieldset>
 
+        <fieldset class="border border-cyan-400 p-4 my-4 rounded-sm">
+          <legend class="px-2 leading-none text-sm">Run rule on</legend>
+          <div class="w-full flex">
+            <div class="relative flex items-center">
+              <input
+                v-model="editRuleObject.forwards"
+                id="forwards"
+                name="forwards"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="forwards" class="ml-2 text-sm text-grey-700">Forwards</label>
+            </div>
+            <div class="relative flex items-center mx-4">
+              <input
+                v-model="editRuleObject.replies"
+                id="replies"
+                name="replies"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="replies" class="ml-2 text-sm text-grey-700">Replies</label>
+            </div>
+            <div class="relative flex items-center">
+              <input
+                v-model="editRuleObject.sends"
+                id="sends"
+                name="sends"
+                type="checkbox"
+                class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
+              />
+              <label for="sends" class="ml-2 text-sm text-grey-700">Sends</label>
+            </div>
+          </div>
+        </fieldset>
+
         <div class="mt-6">
           <button
             @click="editRule"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="editRuleLoading ? 'cursor-not-allowed' : ''"
             :disabled="editRuleLoading"
           >
@@ -1064,18 +807,7 @@
           </button>
           <button
             @click="closeEditModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -1095,17 +827,7 @@
           <button
             type="button"
             @click="deleteRule(ruleIdToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteRuleLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteRuleLoading"
           >
@@ -1114,18 +836,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -1178,6 +889,9 @@ export default {
           },
         ],
         operator: 'AND',
+        forwards: false,
+        replies: false,
+        sends: false,
       },
       rows: this.initialRules,
       conditionTypeOptions: [
@@ -1313,6 +1027,9 @@ export default {
             conditions: this.createRuleObject.conditions,
             actions: this.createRuleObject.actions,
             operator: this.createRuleObject.operator,
+            forwards: this.createRuleObject.forwards,
+            replies: this.createRuleObject.replies,
+            sends: this.createRuleObject.sends,
           }),
           {
             headers: { 'Content-Type': 'application/json' },
@@ -1359,6 +1076,9 @@ export default {
             conditions: this.editRuleObject.conditions,
             actions: this.editRuleObject.actions,
             operator: this.editRuleObject.operator,
+            forwards: this.editRuleObject.forwards,
+            replies: this.editRuleObject.replies,
+            sends: this.editRuleObject.sends,
           }),
           {
             headers: { 'Content-Type': 'application/json' },
@@ -1372,6 +1092,9 @@ export default {
           rule.conditions = this.editRuleObject.conditions
           rule.actions = this.editRuleObject.actions
           rule.operator = this.editRuleObject.operator
+          rule.forwards = this.editRuleObject.forwards
+          rule.replies = this.editRuleObject.replies
+          rule.sends = this.editRuleObject.sends
           this.editRuleObject = {}
           this.editRuleModalOpen = false
           this.success('Rule successfully updated')
@@ -1503,6 +1226,9 @@ export default {
           },
         ],
         operator: 'AND',
+        forwards: false,
+        replies: false,
+        sends: false,
       }
     },
     ruleActionChange(action) {

+ 12 - 140
resources/js/pages/Usernames.vue

@@ -7,71 +7,25 @@
           @keyup.esc="search = ''"
           tabindex="0"
           type="text"
-          class="
-            w-full
-            md:w-64
-            appearance-none
-            shadow
-            bg-white
-            text-grey-700
-            focus:outline-none
-            rounded
-            py-3
-            pl-3
-            pr-8
-          "
+          class="w-full md:w-64 appearance-none shadow bg-white text-grey-700 focus:outline-none rounded py-3 pl-3 pr-8"
           placeholder="Search Usernames"
         />
         <icon
           v-if="search"
           @click.native="search = ''"
           name="close-circle"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            mr-2
-            flex
-            items-center
-            cursor-pointer
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current mr-2 flex items-center cursor-pointer"
         />
         <icon
           v-else
           name="search"
-          class="
-            absolute
-            right-0
-            inset-y-0
-            w-5
-            h-full
-            text-grey-300
-            fill-current
-            pointer-events-none
-            mr-2
-            flex
-            items-center
-          "
+          class="absolute right-0 inset-y-0 w-5 h-full text-grey-300 fill-current pointer-events-none mr-2 flex items-center"
         />
       </div>
       <div class="mt-4 md:mt-0">
         <button
           @click="addUsernameModalOpen = true"
-          class="
-            bg-cyan-400
-            hover:bg-cyan-300
-            text-cyan-900
-            font-bold
-            py-3
-            px-4
-            rounded
-            focus:outline-none
-            ml-auto
-          "
+          class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
         >
           Add Username
         </button>
@@ -121,17 +75,7 @@
               @keyup.esc="usernameIdToEdit = usernameDescriptionToEdit = ''"
               v-model="usernameDescriptionToEdit"
               type="text"
-              class="
-                flex-grow
-                appearance-none
-                bg-grey-100
-                border
-                text-grey-700
-                focus:outline-none
-                rounded
-                px-2
-                py-1
-              "
+              class="flex-grow appearance-none bg-grey-100 border text-grey-700 focus:outline-none rounded px-2 py-1"
               :class="
                 usernameDescriptionToEdit.length > 200 ? 'border-red-500' : 'border-transparent'
               "
@@ -256,33 +200,14 @@
           <input
             v-model="newUsername"
             type="text"
-            class="
-              w-full
-              appearance-none
-              bg-grey-100
-              border border-transparent
-              text-grey-700
-              focus:outline-none
-              rounded
-              p-3
-              mb-6
-            "
+            class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3 mb-6"
             :class="errors.newUsername ? 'border-red-500' : ''"
             placeholder="johndoe"
             autofocus
           />
           <button
             @click="validateNewUsername"
-            class="
-              bg-cyan-400
-              hover:bg-cyan-300
-              text-cyan-900
-              font-bold
-              py-3
-              px-4
-              rounded
-              focus:outline-none
-            "
+            class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none"
             :class="addUsernameLoading ? 'cursor-not-allowed' : ''"
             :disabled="addUsernameLoading"
           >
@@ -291,18 +216,7 @@
           </button>
           <button
             @click="addUsernameModalOpen = false"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -341,17 +255,7 @@
           <button
             type="button"
             @click="editDefaultRecipient()"
-            class="
-              px-4
-              py-3
-              text-cyan-900
-              font-semibold
-              bg-cyan-400
-              hover:bg-cyan-300
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
             :class="editDefaultRecipientLoading ? 'cursor-not-allowed' : ''"
             :disabled="editDefaultRecipientLoading"
           >
@@ -360,18 +264,7 @@
           </button>
           <button
             @click="closeUsernameDefaultRecipientModal()"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>
@@ -396,17 +289,7 @@
           <button
             type="button"
             @click="deleteUsername(usernameIdToDelete)"
-            class="
-              px-4
-              py-3
-              text-white
-              font-semibold
-              bg-red-500
-              hover:bg-red-600
-              border border-transparent
-              rounded
-              focus:outline-none
-            "
+            class="px-4 py-3 text-white font-semibold bg-red-500 hover:bg-red-600 border border-transparent rounded focus:outline-none"
             :class="deleteUsernameLoading ? 'cursor-not-allowed' : ''"
             :disabled="deleteUsernameLoading"
           >
@@ -415,18 +298,7 @@
           </button>
           <button
             @click="closeDeleteModal"
-            class="
-              ml-4
-              px-4
-              py-3
-              text-grey-800
-              font-semibold
-              bg-white
-              hover:bg-grey-50
-              border border-grey-100
-              rounded
-              focus:outline-none
-            "
+            class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
           >
             Cancel
           </button>

+ 81 - 3
tests/Feature/Api/RulesTest.php

@@ -91,7 +91,10 @@ class RulesTest extends TestCase
                     'value' => 'New Subject!'
                 ],
             ],
-            'operator' => 'AND'
+            'operator' => 'AND',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false
         ]);
 
         $response->assertStatus(201);
@@ -118,7 +121,10 @@ class RulesTest extends TestCase
                     'value' => 'New Subject!'
                 ],
             ],
-            'operator' => 'AND'
+            'operator' => 'AND',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false
         ]);
 
         $response->assertStatus(422);
@@ -149,7 +155,10 @@ class RulesTest extends TestCase
                     'value' => 'New Subject!'
                 ],
             ],
-            'operator' => 'OR'
+            'operator' => 'OR',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false
         ]);
 
         $response->assertStatus(200);
@@ -235,6 +244,9 @@ class RulesTest extends TestCase
                 ],
             ],
             'operator' => 'AND',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false
         ]);
 
         $alias = Alias::factory()->create([
@@ -257,6 +269,66 @@ class RulesTest extends TestCase
         $this->assertEquals('New Subject!', $email->subject);
     }
 
+    /** @test */
+    public function it_does_not_apply_rules_if_email_type_is_not_selected()
+    {
+        Rule::factory()->create([
+            'user_id' => $this->user->id,
+            'conditions' => [
+                [
+                    'type' => 'subject',
+                    'match' => 'is exactly',
+                    'values' => [
+                        'Test Email'
+                    ]
+                ],
+                [
+                    'type' => 'sender',
+                    'match' => 'starts with',
+                    'values' => [
+                        'will'
+                    ]
+                ],
+                [
+                    'type' => 'alias',
+                    'match' => 'is exactly',
+                    'values' => [
+                        'ebay@johndoe.anonaddy.com'
+                    ]
+                ]
+            ],
+            'actions' => [
+                [
+                    'type' => 'subject',
+                    'value' => 'New Subject!'
+                ],
+            ],
+            'operator' => 'AND',
+            'forwards' => false,
+            'replies' => true,
+            'sends' => true
+        ]);
+
+        $alias = Alias::factory()->create([
+            'user_id' => $this->user->id,
+            'email' => 'ebay@johndoe.'.config('anonaddy.domain'),
+            'local_part' => 'ebay',
+            'domain' => 'johndoe.'.config('anonaddy.domain'),
+        ]);
+
+        $parser = $this->getParser(base_path('tests/emails/email.eml'));
+
+        $size = 1500;
+
+        $emailData = new EmailData($parser, $size);
+
+        $job = new ForwardEmail($alias, $emailData, $this->user->defaultRecipient);
+
+        $email = $job->build();
+
+        $this->assertEquals($parser->getHeader('subject'), $email->subject);
+    }
+
     /** @test */
     public function it_can_apply_user_rules_in_correct_order()
     {
@@ -278,6 +350,9 @@ class RulesTest extends TestCase
                 ],
             ],
             'operator' => 'AND',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false,
             'order' => 1
         ]);
 
@@ -313,6 +388,9 @@ class RulesTest extends TestCase
                 ],
             ],
             'operator' => 'AND',
+            'forwards' => true,
+            'replies' => false,
+            'sends' => false
         ]);
 
         $alias = Alias::factory()->create([

Some files were not shown because too many files changed in this diff