diff --git a/.DS_Store b/.DS_Store
index 0203e71b2..6d1f51a96 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/CHANGELOG b/CHANGELOG
index 3c3b5de33..23e866a11 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,6 @@
UNRELEASED CHANGES:
-*
+* Add the ability to set as many contact fields to a contact as needed
RELEASED VERSIONS:
diff --git a/app/Account.php b/app/Account.php
index 918814982..952bd61e2 100644
--- a/app/Account.php
+++ b/app/Account.php
@@ -215,7 +215,7 @@ class Account extends Model
}
/**
- * Get the tags records associated with the contact.
+ * Get the tags records associated with the account.
*
* @return HasMany
*/
@@ -225,7 +225,7 @@ class Account extends Model
}
/**
- * Get the calls records associated with the contact.
+ * Get the calls records associated with the account.
*
* @return HasMany
*/
@@ -234,6 +234,26 @@ class Account extends Model
return $this->hasMany(Call::class)->orderBy('called_at', 'desc');
}
+ /**
+ * Get the Contact Field types records associated with the account.
+ *
+ * @return HasMany
+ */
+ public function contactFieldTypes()
+ {
+ return $this->hasMany('App\ContactFieldType');
+ }
+
+ /**
+ * Get the Contact Field records associated with the contact.
+ *
+ * @return HasMany
+ */
+ public function contactFields()
+ {
+ return $this->hasMany('App\ContactField');
+ }
+
/**
* Check if the account can be downgraded, based on a set of rules.
*
@@ -332,4 +352,37 @@ class Account extends Model
return true;
}
+
+ /**
+ * Populates the Contact Field Types table right after an account is
+ * created.
+ */
+ public function populateContactFieldTypeTable($ignoreMigratedTable = false)
+ {
+ $defaultContactFieldTypes = DB::table('default_contact_field_types')->get();
+
+ foreach ($defaultContactFieldTypes as $defaultContactFieldType) {
+ if ($ignoreMigratedTable == false) {
+ $contactFieldType = ContactFieldType::create([
+ 'account_id' => $this->id,
+ 'name' => $defaultContactFieldType->name,
+ 'fontawesome_icon' => (is_null($defaultContactFieldType->fontawesome_icon) ? null : $defaultContactFieldType->fontawesome_icon),
+ 'protocol' => (is_null($defaultContactFieldType->protocol) ? null : $defaultContactFieldType->protocol),
+ 'delible' => $defaultContactFieldType->delible,
+ 'type' => (is_null($defaultContactFieldType->type) ? null : $defaultContactFieldType->type),
+ ]);
+ } else {
+ if ($defaultContactFieldType->migrated == 0) {
+ $contactFieldType = ContactFieldType::create([
+ 'account_id' => $this->id,
+ 'name' => $defaultContactFieldType->name,
+ 'fontawesome_icon' => (is_null($defaultContactFieldType->fontawesome_icon) ? null : $defaultContactFieldType->fontawesome_icon),
+ 'protocol' => (is_null($defaultContactFieldType->protocol) ? null : $defaultContactFieldType->protocol),
+ 'delible' => $defaultContactFieldType->delible,
+ 'type' => (is_null($defaultContactFieldType->type) ? null : $defaultContactFieldType->type),
+ ]);
+ }
+ }
+ }
+ }
}
diff --git a/app/Address.php b/app/Address.php
new file mode 100644
index 000000000..bde556788
--- /dev/null
+++ b/app/Address.php
@@ -0,0 +1,144 @@
+belongsTo(Account::class);
+ }
+
+ /**
+ * Get the contact record associated with the gift.
+ *
+ * @return BelongsTo
+ */
+ public function contact()
+ {
+ return $this->belongsTo(Contact::class);
+ }
+
+ /**
+ * Get the Country records associated with the contact.
+ *
+ * @return BelongsTo
+ */
+ public function country()
+ {
+ return $this->belongsTo('App\Country');
+ }
+
+ /**
+ * Get the address in a format like 'Lives in Scranton, MS'.
+ *
+ * @return string
+ */
+ public function getPartialAddress()
+ {
+ $address = $this->city;
+
+ if (is_null($address)) {
+ return;
+ }
+
+ if (! is_null($this->province)) {
+ $address = $address.', '.$this->province;
+ }
+
+ return $address;
+ }
+
+ /**
+ * Get the address in a format like 'Lives in Scranton, MS'.
+ *
+ * @return string
+ */
+ public function getFullAddress()
+ {
+ $address = '';
+
+ if (! is_null($this->street)) {
+ $address = $this->street;
+ }
+
+ if (! is_null($this->city)) {
+ $address .= ' '.$this->city;
+ }
+
+ if (! is_null($this->province)) {
+ $address .= ' '.$this->province;
+ }
+
+ if (! is_null($this->postal_code)) {
+ $address .= ' '.$this->postal_code;
+ }
+
+ if (! is_null($this->country_id)) {
+ $address .= ' '.$this->country->country;
+ }
+
+ if (is_null($address)) {
+ return;
+ }
+
+ // trim extra whitespaces inside the address
+ $address = preg_replace('/\s+/', ' ', $address);
+
+ return $address;
+ }
+
+ /**
+ * Get the country of the contact.
+ *
+ * @return string or null
+ */
+ public function getCountryName()
+ {
+ if ($this->country) {
+ return $this->country->country;
+ }
+ }
+
+ /**
+ * Get the country ISO of the contact.
+ *
+ * @return string or null
+ */
+ public function getCountryISO()
+ {
+ if ($this->country) {
+ return $this->country->iso;
+ }
+ }
+
+ /**
+ * Get an URL for Google Maps for the address.
+ *
+ * @return string
+ */
+ public function getGoogleMapAddress()
+ {
+ $address = $this->getFullAddress();
+ $address = urlencode($address);
+
+ return "https://www.google.ca/maps/place/{$address}";
+ }
+}
diff --git a/app/Console/Commands/ImportVCards.php b/app/Console/Commands/ImportVCards.php
index 1f4fa6f00..007a3e9be 100644
--- a/app/Console/Commands/ImportVCards.php
+++ b/app/Console/Commands/ImportVCards.php
@@ -3,8 +3,11 @@
namespace App\Console\Commands;
use App\User;
+use App\Address;
use App\Contact;
use App\Country;
+use App\ContactField;
+use App\ContactFieldType;
use Sabre\VObject\Reader;
use Illuminate\Console\Command;
use Sabre\VObject\Component\VCard;
@@ -107,29 +110,53 @@ class ImportVCards extends Command
$contact->birthdate = new \DateTime((string) $vcard->BDAY);
}
- $contact->email = $this->formatValue($vcard->EMAIL);
- $contact->phone_number = $this->formatValue($vcard->TEL);
+ $contact->job = $this->formatValue($vcard->ORG);
+
+ $contact->setAvatarColor();
+
+ $contact->save();
if ($vcard->ADR) {
- $contact->street = $this->formatValue($vcard->ADR->getParts()[2]);
- $contact->city = $this->formatValue($vcard->ADR->getParts()[3]);
- $contact->province = $this->formatValue($vcard->ADR->getParts()[4]);
- $contact->postal_code = $this->formatValue($vcard->ADR->getParts()[5]);
+ $address = new Address();
+ $address->street = $this->formatValue($vcard->ADR->getParts()[2]);
+ $address->city = $this->formatValue($vcard->ADR->getParts()[3]);
+ $address->province = $this->formatValue($vcard->ADR->getParts()[4]);
+ $address->postal_code = $this->formatValue($vcard->ADR->getParts()[5]);
$country = Country::where('country', $vcard->ADR->getParts()[6])
->orWhere('iso', strtolower($vcard->ADR->getParts()[6]))
->first();
if ($country) {
- $contact->country_id = $country->id;
+ $address->country_id = $country->id;
}
+
+ $address->contact_id = $contact->id;
+ $address->account_id = $contact->account_id;
+ $address->save();
}
- $contact->job = $this->formatValue($vcard->ORG);
+ if (! is_null($this->formatValue($vcard->EMAIL))) {
+ // Saves the email
+ $contactFieldType = ContactFieldType::where('type', 'email')->first();
+ $contactField = new ContactField;
+ $contactField->account_id = $contact->account_id;
+ $contactField->contact_id = $contact->id;
+ $contactField->data = $this->formatValue($vcard->EMAIL);
+ $contactField->contact_field_type_id = $contactFieldType->id;
+ $contactField->save();
+ }
- $contact->setAvatarColor();
-
- $contact->save();
+ if (! is_null($this->formatValue($vcard->TEL))) {
+ // Saves the phone number
+ $contactFieldType = ContactFieldType::where('type', 'phone')->first();
+ $contactField = new ContactField;
+ $contactField->account_id = $contact->account_id;
+ $contactField->contact_id = $contact->id;
+ $contactField->data = $this->formatValue($vcard->TEL);
+ $contactField->contact_field_type_id = $contactFieldType->id;
+ $contactField->save();
+ }
$contact->logEvent('contact', $contact->id, 'create');
@@ -164,12 +191,22 @@ class ImportVCards extends Command
{
$email = (string) $vcard->EMAIL;
- $contact = Contact::where([
+ $contactFieldType = ContactFieldType::where([
['account_id', $user->account_id],
- ['email', $email],
+ ['type', 'email'],
])->first();
- return $email && $contact;
+ $contactField = null;
+
+ if ($contactFieldType) {
+ $contactField = ContactField::where([
+ ['account_id', $user->account_id],
+ ['data', $email],
+ ['contact_field_type_id', $contactFieldType->id],
+ ])->first();
+ }
+
+ return $email && $contactField;
}
/**
diff --git a/app/Console/Commands/ResetTestDB.php b/app/Console/Commands/ResetTestDB.php
index a5003f65e..198eaff46 100644
--- a/app/Console/Commands/ResetTestDB.php
+++ b/app/Console/Commands/ResetTestDB.php
@@ -44,8 +44,8 @@ class ResetTestDB extends Command
\Schema::drop($table_array[key($table_array)]);
}
- $this->call('migrate');
- $this->call('db:seed');
+ //$this->call('migrate');
+ //$this->call('db:seed');
$this->info('Local database has been reset');
} else {
$this->info('Can\'t execute this command in this environment');
diff --git a/app/Contact.php b/app/Contact.php
index 6bad19630..a3f2bffe2 100644
--- a/app/Contact.php
+++ b/app/Contact.php
@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\Builder;
use App\Http\Resources\Tag\Tag as TagResource;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use App\Http\Resources\Address\AddressShort as AddressShortResource;
use App\Http\Resources\Contact\PartnerShort as PartnerShortResource;
use App\Http\Resources\Contact\OffspringShort as OffspringShortResource;
use App\Http\Resources\Contact\ProgenitorShort as ProgenitorShortResource;
@@ -32,11 +33,6 @@ class Contact extends Model
'first_name',
'middle_name',
'last_name',
- 'email',
- 'street',
- 'city',
- 'postal_code',
- 'province',
'food_preferencies',
'job',
'company',
@@ -68,18 +64,9 @@ class Contact extends Model
'is_birthdate_approximate',
'account_id',
'is_partial',
- 'phone_number',
- 'email',
'job',
'company',
- 'street',
- 'city',
- 'province',
- 'postal_code',
- 'country_id',
'food_preferencies',
- 'facebook_profile_url',
- 'twitter_profile_url',
'linkedin_profile_url',
'is_dead',
'deceased_date',
@@ -139,16 +126,6 @@ class Contact extends Model
return $this->hasMany('App\ActivityStatistic');
}
- /**
- * Get the contact records associated with the contact.
- *
- * @return BelongsTo
- */
- public function country()
- {
- return $this->belongsTo('App\Country');
- }
-
/**
* Get the debt records associated with the contact.
*
@@ -269,6 +246,26 @@ class Contact extends Model
return $this->hasMany('App\Progenitor', 'is_the_parent_of');
}
+ /**
+ * Get the Contact Field records associated with the contact.
+ *
+ * @return HasMany
+ */
+ public function contactFields()
+ {
+ return $this->hasMany('App\ContactField');
+ }
+
+ /**
+ * Get the Address Field records associated with the contact.
+ *
+ * @return HasMany
+ */
+ public function addresses()
+ {
+ return $this->hasMany('App\Address');
+ }
+
/**
* Sort the contacts according a given criteria.
* @param Builder $builder
@@ -473,63 +470,6 @@ class Contact extends Model
return $this->is_birthdate_approximate;
}
- /**
- * Get the address in a format like 'Lives in Scranton, MS'.
- *
- * @return string
- */
- public function getPartialAddress()
- {
- $address = $this->city;
-
- if (is_null($address)) {
- return;
- }
-
- if (! is_null($this->province)) {
- $address = $address.', '.$this->province;
- }
-
- return $address;
- }
-
- /**
- * Get the country of the contact.
- *
- * @return string or null
- */
- public function getCountryName()
- {
- if ($this->country) {
- return $this->country->country;
- }
- }
-
- /**
- * Get the country ISO of the contact.
- *
- * @return string or null
- */
- public function getCountryISO()
- {
- if ($this->country) {
- return $this->country->iso;
- }
- }
-
- /**
- * Get an URL for Google Maps for the address.
- *
- * @return string
- */
- public function getGoogleMapAddress()
- {
- $address = $this->getFullAddress();
- $address = urlencode($address);
-
- return "https://www.google.ca/maps/place/{$address}";
- }
-
/**
* Get the current Significant Others, if they exists, or return null otherwise.
*
@@ -849,6 +789,14 @@ class Contact extends Model
return TagResource::collection($this->tags);
}
+ /**
+ * Get the list of addresses for this contact.
+ */
+ public function getAddressesForAPI()
+ {
+ return AddressShortResource::collection($this->addresses);
+ }
+
/**
* Update the last called info on the contact, if the call has been made
* in the most recent date.
diff --git a/app/ContactField.php b/app/ContactField.php
new file mode 100644
index 000000000..a150b2866
--- /dev/null
+++ b/app/ContactField.php
@@ -0,0 +1,46 @@
+belongsTo(Account::class);
+ }
+
+ /**
+ * Get the contact record associated with the gift.
+ *
+ * @return BelongsTo
+ */
+ public function contact()
+ {
+ return $this->belongsTo(Contact::class);
+ }
+
+ /**
+ * Get the contact record associated with the gift.
+ *
+ * @return BelongsTo
+ */
+ public function contactFieldType()
+ {
+ return $this->belongsTo(ContactFieldType::class);
+ }
+}
diff --git a/app/ContactFieldType.php b/app/ContactFieldType.php
new file mode 100644
index 000000000..cf48ff0a8
--- /dev/null
+++ b/app/ContactFieldType.php
@@ -0,0 +1,28 @@
+belongsTo(Account::class);
+ }
+}
diff --git a/app/Http/Controllers/Api/ApiAddressController.php b/app/Http/Controllers/Api/ApiAddressController.php
new file mode 100644
index 000000000..60bed5154
--- /dev/null
+++ b/app/Http/Controllers/Api/ApiAddressController.php
@@ -0,0 +1,167 @@
+user()->account_id)
+ ->where('id', $id)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ return new AddressResource($address);
+ }
+
+ /**
+ * Store the address.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(Request $request)
+ {
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'name' => 'max:255|required',
+ 'street' => 'max:255|nullable',
+ 'city' => 'max:255|nullable',
+ 'province' => 'max:255|nullable',
+ 'postal_code' => 'max:255|nullable',
+ 'country_id' => 'integer|nullable',
+ 'contact_id' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $request->input('contact_id'))
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ try {
+ $address = Address::create(
+ $request->all()
+ + [
+ 'account_id' => auth()->user()->account->id,
+ ]
+ );
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new AddressResource($address);
+ }
+
+ /**
+ * Update the address.
+ * @param Request $request
+ * @param int $addressId
+ * @return \Illuminate\Http\Response
+ */
+ public function update(Request $request, $addressId)
+ {
+ try {
+ $address = Address::where('account_id', auth()->user()->account_id)
+ ->where('id', $addressId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'name' => 'max:255|required',
+ 'street' => 'max:255|nullable',
+ 'city' => 'max:255|nullable',
+ 'province' => 'max:255|nullable',
+ 'postal_code' => 'max:255|nullable',
+ 'country_id' => 'integer|nullable',
+ 'contact_id' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $request->input('contact_id'))
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ try {
+ $address->update($request->all());
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new AddressResource($address);
+ }
+
+ /**
+ * Delete a address.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy(Request $request, $addressId)
+ {
+ try {
+ $address = Address::where('account_id', auth()->user()->account_id)
+ ->where('id', $addressId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ $address->delete();
+
+ return $this->respondObjectDeleted($address->id);
+ }
+
+ /**
+ * Get the list of addresses for the given contact.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function addresses(Request $request, $contactId)
+ {
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ $addresses = $contact->addresses()
+ ->paginate($this->getLimitPerPage());
+
+ return AddressResource::collection($addresses);
+ }
+}
diff --git a/app/Http/Controllers/Api/ApiContactController.php b/app/Http/Controllers/Api/ApiContactController.php
index bf3adb137..021714485 100644
--- a/app/Http/Controllers/Api/ApiContactController.php
+++ b/app/Http/Controllers/Api/ApiContactController.php
@@ -70,11 +70,6 @@ class ApiContactController extends ApiController
'phone_number' => 'nullable|max:255',
'job' => 'nullable|max:255',
'company' => 'nullable|max:255',
- 'street' => 'nullable|max:255',
- 'city' => 'nullable|max:255',
- 'province' => 'nullable|max:255',
- 'postal_code' => 'nullable|max:255',
- 'country_id' => 'nullable|integer|max:255',
'food_preferencies' => 'nullable|max:100000',
'facebook_profile_url' => 'nullable|max:255',
'twitter_profile_url' => 'nullable|max:255',
@@ -179,11 +174,6 @@ class ApiContactController extends ApiController
'phone_number' => 'nullable|max:255',
'job' => 'nullable|max:255',
'company' => 'nullable|max:255',
- 'street' => 'nullable|max:255',
- 'city' => 'nullable|max:255',
- 'province' => 'nullable|max:255',
- 'postal_code' => 'nullable|max:255',
- 'country_id' => 'nullable|integer|max:255',
'food_preferencies' => 'nullable|max:100000',
'facebook_profile_url' => 'nullable|max:255',
'twitter_profile_url' => 'nullable|max:255',
@@ -284,6 +274,7 @@ class ApiContactController extends ApiController
$contact->reminders->each->delete();
$contact->tags->each->delete();
$contact->tasks->each->delete();
+ $contact->addresses->each->delete();
// delete all relationships
$relationships = Relationship::where('contact_id', $contact->id)
diff --git a/app/Http/Controllers/Api/ApiContactFieldController.php b/app/Http/Controllers/Api/ApiContactFieldController.php
new file mode 100644
index 000000000..6348a62a5
--- /dev/null
+++ b/app/Http/Controllers/Api/ApiContactFieldController.php
@@ -0,0 +1,168 @@
+user()->account_id)
+ ->where('id', $id)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ return new ContactFieldResource($contactField);
+ }
+
+ /**
+ * Store the contactField.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(Request $request)
+ {
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'data' => 'max:255|required',
+ 'contact_field_type_id' => 'integer|required',
+ 'contact_id' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $request->input('contact_id'))
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $request->input('contact_field_type_id'))
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ try {
+ $contactField = ContactField::create(
+ $request->all()
+ + [
+ 'account_id' => auth()->user()->account->id,
+ ]
+ );
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new ContactFieldResource($contactField);
+ }
+
+ /**
+ * Update the contactField.
+ * @param Request $request
+ * @param int $contactFieldId
+ * @return \Illuminate\Http\Response
+ */
+ public function update(Request $request, $contactFieldId)
+ {
+ try {
+ $contactField = ContactField::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'data' => 'max:255|required',
+ 'contact_field_type_id' => 'integer|required',
+ 'contact_id' => 'required|integer',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $request->input('contact_id'))
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ try {
+ $contactField->update($request->all());
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new ContactFieldResource($contactField);
+ }
+
+ /**
+ * Delete a contactField.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy(Request $request, $contactFieldId)
+ {
+ try {
+ $contactField = ContactField::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ $contactField->delete();
+
+ return $this->respondObjectDeleted($contactField->id);
+ }
+
+ /**
+ * Get the list of contact fields for the given contact.
+ *
+ * @return \Illuminate\Http\Response
+ */
+ public function contactFields(Request $request, $contactId)
+ {
+ try {
+ $contact = Contact::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ $contactFields = $contact->contactFields()
+ ->paginate($this->getLimitPerPage());
+
+ return ContactFieldResource::collection($contactFields);
+ }
+}
diff --git a/app/Http/Controllers/Api/Misc/ApiCountryController.php b/app/Http/Controllers/Api/Misc/ApiCountryController.php
new file mode 100644
index 000000000..666a5488f
--- /dev/null
+++ b/app/Http/Controllers/Api/Misc/ApiCountryController.php
@@ -0,0 +1,23 @@
+get();
+
+ return CountryResource::collection($countries);
+ }
+}
diff --git a/app/Http/Controllers/Api/Settings/ApiContactFieldTypeController.php b/app/Http/Controllers/Api/Settings/ApiContactFieldTypeController.php
new file mode 100644
index 000000000..a60ab039e
--- /dev/null
+++ b/app/Http/Controllers/Api/Settings/ApiContactFieldTypeController.php
@@ -0,0 +1,153 @@
+user()->account->contactFieldTypes()
+ ->paginate($this->getLimitPerPage());
+
+ return ContactFieldTypeResource::collection($contactFieldTypes);
+ }
+
+ /**
+ * Get the detail of a given contact field type.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function show(Request $request, $contactFieldTypeId)
+ {
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldTypeId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ return new ContactFieldTypeResource($contactFieldType);
+ }
+
+ /**
+ * Store the contactfieldtype.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function store(Request $request)
+ {
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'name' => 'required|max:255',
+ 'fontawesome_icon' => 'nullable|max:255',
+ 'protocol' => 'nullable|max:255',
+ 'delible' => 'integer',
+ 'type' => 'nullable|max:255',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ try {
+ $contactFieldType = ContactFieldType::create(
+ $request->all()
+ + ['account_id' => auth()->user()->account->id]
+ );
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new ContactFieldTypeResource($contactFieldType);
+ }
+
+ /**
+ * Update the contact field type.
+ * @param Request $request
+ * @param int
+ * @return \Illuminate\Http\Response
+ */
+ public function update(Request $request, $contactFieldTypeId)
+ {
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldTypeId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ // Validates basic fields to create the entry
+ $validator = Validator::make($request->all(), [
+ 'name' => 'required|max:255',
+ 'fontawesome_icon' => 'nullable|max:255',
+ 'protocol' => 'nullable|max:255',
+ 'delible' => 'integer',
+ 'type' => 'nullable|max:255',
+ ]);
+
+ if ($validator->fails()) {
+ return $this->setErrorCode(32)
+ ->respondWithError($validator->errors()->all());
+ }
+
+ // Update the contactfieldtype itself
+ try {
+ $contactFieldType->update(
+ $request->only([
+ 'name',
+ 'fontawesome_icon',
+ 'protocol',
+ 'delible',
+ 'type',
+ ])
+ );
+ } catch (QueryException $e) {
+ return $this->respondNotTheRightParameters();
+ }
+
+ return new ContactFieldTypeResource($contactFieldType);
+ }
+
+ /**
+ * Delete an contactfieldtype.
+ * @param Request $request
+ * @return \Illuminate\Http\Response
+ */
+ public function destroy(Request $request, $contactFieldTypeId)
+ {
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldTypeId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respondNotFound();
+ }
+
+ $contactFields = auth()->user()->account->contactFields
+ ->where('contact_field_type_id', $contactFieldTypeId);
+
+ foreach ($contactFields as $contactField) {
+ $contactField->delete();
+ }
+
+ $contactFieldType->delete();
+
+ return $this->respondObjectDeleted($contactFieldType->id);
+ }
+}
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 8e8aeda02..433279793 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -99,6 +99,8 @@ class RegisterController extends Controller
$user->account_id = $account->id;
$user->save();
+ $account->populateContactFieldTypeTable();
+
// send me an alert
dispatch(new SendNewUserAlert($user));
diff --git a/app/Http/Controllers/People/AddressesController.php b/app/Http/Controllers/People/AddressesController.php
new file mode 100644
index 000000000..a0623fddc
--- /dev/null
+++ b/app/Http/Controllers/People/AddressesController.php
@@ -0,0 +1,88 @@
+addresses as $address) {
+ $data = [
+ 'id' => $address->id,
+ 'name' => $address->name,
+ 'googleMapAddress' => $address->getGoogleMapAddress(),
+ 'address' => $address->getFullAddress(),
+ 'country_id' => $address->country_id,
+ 'name' => $address->name,
+ 'street' => $address->street,
+ 'city' => $address->city,
+ 'province' => $address->province,
+ 'postal_code' => $address->postal_code,
+ 'edit' => false,
+ ];
+ $contactAddresses->push($data);
+ }
+
+ return $contactAddresses;
+ }
+
+ /**
+ * Get all the countries.
+ */
+ public function getCountries()
+ {
+ return Country::all();
+ }
+
+ /**
+ * Store the address.
+ */
+ public function store(AddressesRequest $request, Contact $contact)
+ {
+ $address = $contact->addresses()->create([
+ 'account_id' => auth()->user()->account->id,
+ 'country_id' => ($request->get('country_id') == 0 ? null : $request->get('country_id')),
+ 'name' => ($request->get('name') == '' ? null : $request->get('name')),
+ 'street' => ($request->get('street') == '' ? null : $request->get('street')),
+ 'city' => ($request->get('city') == '' ? null : $request->get('city')),
+ 'province' => ($request->get('province') == '' ? null : $request->get('province')),
+ 'postal_code' => ($request->get('postal_code') == '' ? null : $request->get('postal_code')),
+ ]);
+
+ return $address;
+ }
+
+ /**
+ * Edit the contact field.
+ */
+ public function edit(AddressesRequest $request, Contact $contact, Address $address)
+ {
+ $address->update([
+ 'country_id' => ($request->get('country_id') == 0 ? null : $request->get('country_id')),
+ 'name' => ($request->get('name') == '' ? null : $request->get('name')),
+ 'street' => ($request->get('street') == '' ? null : $request->get('street')),
+ 'city' => ($request->get('city') == '' ? null : $request->get('city')),
+ 'province' => ($request->get('province') == '' ? null : $request->get('province')),
+ 'postal_code' => ($request->get('postal_code') == '' ? null : $request->get('postal_code')),
+ ]);
+
+ return $address;
+ }
+
+ public function destroy(Contact $contact, Address $address)
+ {
+ $address->delete();
+ }
+}
diff --git a/app/Http/Controllers/People/ContactFieldsController.php b/app/Http/Controllers/People/ContactFieldsController.php
new file mode 100644
index 000000000..85830363b
--- /dev/null
+++ b/app/Http/Controllers/People/ContactFieldsController.php
@@ -0,0 +1,85 @@
+contactFields as $contactField) {
+ $data = [
+ 'id' => $contactField->id,
+ 'data' => $contactField->data,
+ 'name' => $contactField->contactFieldType->name,
+ 'fontawesome_icon' => (is_null($contactField->contactFieldType->fontawesome_icon) ? null : $contactField->contactFieldType->fontawesome_icon),
+ 'protocol' => (is_null($contactField->contactFieldType->protocol) ? null : $contactField->contactFieldType->protocol),
+ 'contact_field_type_id' => $contactField->contact_field_type_id,
+ 'edit' => false,
+ ];
+ $contactInformationData->push($data);
+ }
+
+ return $contactInformationData;
+ }
+
+ /**
+ * Get all the contact field types.
+ * @param Contact $contact
+ */
+ public function getContactFieldTypes(Contact $contact)
+ {
+ return auth()->user()->account->contactFieldTypes;
+ }
+
+ /**
+ * Store the contact field.
+ */
+ public function storeContactField(ContactFieldsRequest $request, Contact $contact)
+ {
+ $contactField = $contact->contactFields()->create(
+ $request->only([
+ 'contact_field_type_id',
+ 'data',
+ ])
+ + [
+ 'account_id' => auth()->user()->account->id,
+ ]
+ );
+
+ return $contactField;
+ }
+
+ /**
+ * Edit the contact field.
+ */
+ public function editContactField(ContactFieldsRequest $request, Contact $contact, ContactField $contactField)
+ {
+ $contactField->update(
+ $request->only([
+ 'contact_field_type_id',
+ 'data',
+ ])
+ + [
+ 'account_id' => auth()->user()->account->id,
+ ]
+ );
+
+ return $contactField;
+ }
+
+ public function destroyContactField(Contact $contact, ContactField $contactField)
+ {
+ $contactField->delete();
+ }
+}
diff --git a/app/Http/Controllers/PeopleController.php b/app/Http/Controllers/PeopleController.php
index d61fa494e..bdbd37906 100644
--- a/app/Http/Controllers/PeopleController.php
+++ b/app/Http/Controllers/PeopleController.php
@@ -186,60 +186,6 @@ class PeopleController extends Controller
$contact->avatar_file_name = $request->avatar->store('avatars', config('filesystems.default'));
}
- if ($request->input('email') != '') {
- $contact->email = $request->input('email');
- } else {
- $contact->email = null;
- }
-
- if ($request->input('phone') != '') {
- $contact->phone_number = $request->input('phone');
- } else {
- $contact->phone_number = null;
- }
-
- if ($request->input('facebook') != '') {
- $contact->facebook_profile_url = $request->input('facebook');
- } else {
- $contact->facebook_profile_url = null;
- }
-
- if ($request->input('twitter') != '') {
- $contact->twitter_profile_url = $request->input('twitter');
- } else {
- $contact->twitter_profile_url = null;
- }
-
- if ($request->input('street') != '') {
- $contact->street = $request->input('street');
- } else {
- $contact->street = null;
- }
-
- if ($request->input('postalcode') != '') {
- $contact->postal_code = $request->input('postalcode');
- } else {
- $contact->postal_code = null;
- }
-
- if ($request->input('province') != '') {
- $contact->province = $request->input('province');
- } else {
- $contact->province = null;
- }
-
- if ($request->input('city') != '') {
- $contact->city = $request->input('city');
- } else {
- $contact->city = null;
- }
-
- if ($request->input('country') != '---') {
- $contact->country_id = $request->input('country');
- } else {
- $contact->country_id = null;
- }
-
// Is the person deceased?
if ($request->input('markPersonDeceased') != '') {
$contact->is_dead = true;
@@ -322,6 +268,8 @@ class PeopleController extends Controller
$contact->reminders->each->delete();
$contact->tags->each->delete();
$contact->tasks->each->delete();
+ $contact->contactFields->each->delete();
+ $contact->addresses->each->delete();
// delete all relationships
$relationships = Relationship::where('contact_id', $contact->id)
diff --git a/app/Http/Controllers/Settings/PersonalizationController.php b/app/Http/Controllers/Settings/PersonalizationController.php
new file mode 100644
index 000000000..bf44bd479
--- /dev/null
+++ b/app/Http/Controllers/Settings/PersonalizationController.php
@@ -0,0 +1,129 @@
+user()->account->contactFieldTypes;
+ }
+
+ /**
+ * Store a newly created resource in storage.
+ *
+ * @param Request $request
+ * @return string
+ */
+ public function storeContactFieldType(Request $request)
+ {
+ Validator::make($request->all(), [
+ 'name' => 'required|max:255',
+ 'icon' => 'max:255|nullable',
+ 'protocol' => 'max:255|nullable',
+ ])->validate();
+
+ $contactFieldType = auth()->user()->account->contactFieldTypes()->create(
+ $request->only([
+ 'name',
+ 'protocol',
+ ])
+ + [
+ 'fontawesome_icon' => $request->get('icon'),
+ 'account_id' => auth()->user()->account->id,
+ ]
+ );
+
+ return $contactFieldType;
+ }
+
+ /**
+ * Edit a newly created resource in storage.
+ *
+ * @param ContactFieldTypeRequest $request
+ * @param string $contactFieldTypeId
+ * @return \Illuminate\Http\Response
+ */
+ public function editContactFieldType(Request $request, $contactFieldTypeId)
+ {
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldTypeId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respond([
+ 'errors' => [
+ 'message' => trans('app.error_unauthorized'),
+ ],
+ ]);
+ }
+
+ Validator::make($request->all(), [
+ 'name' => 'required|max:255',
+ 'icon' => 'max:255|nullable',
+ 'protocol' => 'max:255|nullable',
+ ])->validate();
+
+ $contactFieldType->update(
+ $request->only([
+ 'name',
+ 'protocol',
+ ])
+ + [
+ 'fontawesome_icon' => $request->get('icon'),
+ ]
+ );
+
+ return $contactFieldType;
+ }
+
+ public function destroyContactFieldType(Request $request, $contactFieldTypeId)
+ {
+ try {
+ $contactFieldType = ContactFieldType::where('account_id', auth()->user()->account_id)
+ ->where('id', $contactFieldTypeId)
+ ->firstOrFail();
+ } catch (ModelNotFoundException $e) {
+ return $this->respond([
+ 'errors' => [
+ 'message' => trans('app.error_unauthorized'),
+ ],
+ ]);
+ }
+
+ if ($contactFieldType->delible == false) {
+ return $this->respond([
+ 'errors' => [
+ 'message' => trans('app.error_unauthorized'),
+ ],
+ ]);
+ }
+
+ // find all the contact fields that have this contact field types
+ $contactFields = auth()->user()->account->contactFields
+ ->where('contact_field_type_id', $contactFieldTypeId);
+
+ foreach ($contactFields as $contactField) {
+ $contactField->delete();
+ }
+
+ $contactFieldType->delete();
+ }
+}
diff --git a/app/Http/Requests/People/AddressesRequest.php b/app/Http/Requests/People/AddressesRequest.php
new file mode 100644
index 000000000..e7d84b232
--- /dev/null
+++ b/app/Http/Requests/People/AddressesRequest.php
@@ -0,0 +1,35 @@
+ 'integer|nullable',
+ 'name' => 'max:255|nullable',
+ 'street' => 'max:255|nullable',
+ 'city' => 'max:255|nullable',
+ 'province' => 'max:255|nullable',
+ 'postal_code' => 'max:255|nullable',
+ ];
+ }
+}
diff --git a/app/Http/Requests/People/ContactFieldsRequest.php b/app/Http/Requests/People/ContactFieldsRequest.php
new file mode 100644
index 000000000..5d9573fb2
--- /dev/null
+++ b/app/Http/Requests/People/ContactFieldsRequest.php
@@ -0,0 +1,31 @@
+ 'required',
+ 'data' => 'max:255|required',
+ ];
+ }
+}
diff --git a/app/Http/Resources/Address/Address.php b/app/Http/Resources/Address/Address.php
new file mode 100644
index 000000000..151ab21a1
--- /dev/null
+++ b/app/Http/Resources/Address/Address.php
@@ -0,0 +1,36 @@
+ $this->id,
+ 'object' => 'address',
+ 'name' => $this->name,
+ 'street' => $this->street,
+ 'city' => $this->city,
+ 'province' => $this->province,
+ 'postal_code' => $this->postal_code,
+ 'country' => new CountryResource($this->country),
+ 'account' => [
+ 'id' => $this->account_id,
+ ],
+ 'contact' => new ContactShortResource($this->contact),
+ 'created_at' => (is_null($this->created_at) ? null : $this->created_at->format(config('api.timestamp_format'))),
+ 'updated_at' => (is_null($this->updated_at) ? null : $this->updated_at->format(config('api.timestamp_format'))),
+ ];
+ }
+}
diff --git a/app/Http/Resources/Address/AddressCollection.php b/app/Http/Resources/Address/AddressCollection.php
new file mode 100644
index 000000000..8123c2a9e
--- /dev/null
+++ b/app/Http/Resources/Address/AddressCollection.php
@@ -0,0 +1,24 @@
+ $this->collection,
+ 'links' => [
+ 'self' => 'link-value',
+ ],
+ ];
+ }
+}
diff --git a/app/Http/Resources/Address/AddressShort.php b/app/Http/Resources/Address/AddressShort.php
new file mode 100644
index 000000000..a815a1cef
--- /dev/null
+++ b/app/Http/Resources/Address/AddressShort.php
@@ -0,0 +1,31 @@
+ $this->id,
+ 'object' => 'address',
+ 'name' => $this->name,
+ 'street' => $this->street,
+ 'city' => $this->city,
+ 'province' => $this->province,
+ 'postal_code' => $this->postal_code,
+ 'country' => new CountryResource($this->country),
+ 'created_at' => (is_null($this->created_at) ? null : $this->created_at->format(config('api.timestamp_format'))),
+ 'updated_at' => (is_null($this->updated_at) ? null : $this->updated_at->format(config('api.timestamp_format'))),
+ ];
+ }
+}
diff --git a/app/Http/Resources/Contact/Contact.php b/app/Http/Resources/Contact/Contact.php
index 374532764..8ef2b39b9 100644
--- a/app/Http/Resources/Contact/Contact.php
+++ b/app/Http/Resources/Contact/Contact.php
@@ -80,18 +80,8 @@ class Contact extends Resource
'twitter_profile_url' => $this->twitter_profile_url,
'linkedin_profile_url' => $this->linkedin_profile_url,
],
- 'addresses' => [
- [
- 'name' => 'home',
- 'street' => $this->street,
- 'city' => $this->city,
- 'province' => $this->province,
- 'postal_code' => $this->postal_code,
- 'country_id' => $this->country_id,
- 'country_name' => $this->getCountryName(),
- ],
- ],
]),
+ 'addresses' => $this->when(! $this->is_partial, $this->getAddressesForAPI()),
'tags' => $this->when(! $this->is_partial, $this->getTagsForAPI()),
'statistics' => $this->when(! $this->is_partial, [
'number_of_calls' => $this->calls->count(),
diff --git a/app/Http/Resources/ContactField/ContactField.php b/app/Http/Resources/ContactField/ContactField.php
new file mode 100644
index 000000000..86b412533
--- /dev/null
+++ b/app/Http/Resources/ContactField/ContactField.php
@@ -0,0 +1,32 @@
+ $this->id,
+ 'object' => 'contactfield',
+ 'data' => $this->data,
+ 'contact_field_type' => new ContactFieldTypeResource($this->contactFieldType),
+ 'account' => [
+ 'id' => $this->account->id,
+ ],
+ 'contact' => new ContactShortResource($this->contact),
+ 'created_at' => $this->created_at->format(config('api.timestamp_format')),
+ 'updated_at' => (is_null($this->updated_at) ? null : $this->updated_at->format(config('api.timestamp_format'))),
+ ];
+ }
+}
diff --git a/app/Http/Resources/Country/Country.php b/app/Http/Resources/Country/Country.php
new file mode 100644
index 000000000..f8473fcb8
--- /dev/null
+++ b/app/Http/Resources/Country/Country.php
@@ -0,0 +1,24 @@
+ $this->id,
+ 'object' => 'country',
+ 'name' => $this->country,
+ 'iso' => $this->iso,
+ ];
+ }
+}
diff --git a/app/Http/Resources/Country/CountryCollection.php b/app/Http/Resources/Country/CountryCollection.php
new file mode 100644
index 000000000..9b5816464
--- /dev/null
+++ b/app/Http/Resources/Country/CountryCollection.php
@@ -0,0 +1,24 @@
+ $this->collection,
+ 'links' => [
+ 'self' => 'link-value',
+ ],
+ ];
+ }
+}
diff --git a/app/Http/Resources/Settings/ContactFieldType/ContactFieldType.php b/app/Http/Resources/Settings/ContactFieldType/ContactFieldType.php
new file mode 100644
index 000000000..0ea5f5af2
--- /dev/null
+++ b/app/Http/Resources/Settings/ContactFieldType/ContactFieldType.php
@@ -0,0 +1,32 @@
+ $this->id,
+ 'object' => 'contactfieldtype',
+ 'name' => $this->name,
+ 'fontawesome_icon' => $this->fontawesome_icon,
+ 'protocol' => $this->protocol,
+ 'delible' => (bool) $this->delible,
+ 'type' => $this->type,
+ 'account' => [
+ 'id' => $this->account->id,
+ ],
+ 'created_at' => $this->created_at->format(config('api.timestamp_format')),
+ 'updated_at' => (is_null($this->updated_at) ? null : $this->updated_at->format(config('api.timestamp_format'))),
+ ];
+ }
+}
diff --git a/app/Http/Resources/Settings/ContactFieldType/ContactFieldTypeCollection.php b/app/Http/Resources/Settings/ContactFieldType/ContactFieldTypeCollection.php
new file mode 100644
index 000000000..9dd277d48
--- /dev/null
+++ b/app/Http/Resources/Settings/ContactFieldType/ContactFieldTypeCollection.php
@@ -0,0 +1,24 @@
+ $this->collection,
+ 'links' => [
+ 'self' => 'link-value',
+ ],
+ ];
+ }
+}
diff --git a/app/Instance.php b/app/Instance.php
index 1697793df..561a1a285 100644
--- a/app/Instance.php
+++ b/app/Instance.php
@@ -2,8 +2,20 @@
namespace App;
+use DB;
use Illuminate\Database\Eloquent\Model;
class Instance extends Model
{
+ /**
+ * Once migrations have been run to add a new default contact field type,
+ * we need to mark the field as being migrated so we don't create another
+ * default contact field type if another migration will change this table
+ * in the future.
+ */
+ public function markDefaultContactFieldTypeAsMigrated()
+ {
+ DB::table('default_contact_field_types')
+ ->update(['migrated' => 1]);
+ }
}
diff --git a/app/Jobs/AddContactFromVCard.php b/app/Jobs/AddContactFromVCard.php
index 4e29625e0..b03c5da52 100644
--- a/app/Jobs/AddContactFromVCard.php
+++ b/app/Jobs/AddContactFromVCard.php
@@ -3,11 +3,14 @@
namespace App\Jobs;
use App\User;
+use App\Address;
use App\Contact;
use App\Country;
use App\Reminder;
use App\ImportJob;
+use App\ContactField;
use App\ImportJobReport;
+use App\ContactFieldType;
use Sabre\VObject\Reader;
use Illuminate\Bus\Queueable;
use Sabre\VObject\Component\VCard;
@@ -90,29 +93,53 @@ class AddContactFromVCard implements ShouldQueue
$contact->birthdate = new \DateTime((string) $vcard->BDAY);
}
- $contact->email = $this->formatValue($vcard->EMAIL);
- $contact->phone_number = $this->formatValue($vcard->TEL);
+ $contact->job = $this->formatValue($vcard->ORG);
+
+ $contact->setAvatarColor();
+
+ $contact->save();
if ($vcard->ADR) {
- $contact->street = $this->formatValue($vcard->ADR->getParts()[2]);
- $contact->city = $this->formatValue($vcard->ADR->getParts()[3]);
- $contact->province = $this->formatValue($vcard->ADR->getParts()[4]);
- $contact->postal_code = $this->formatValue($vcard->ADR->getParts()[5]);
+ $address = new Address();
+ $address->street = $this->formatValue($vcard->ADR->getParts()[2]);
+ $address->city = $this->formatValue($vcard->ADR->getParts()[3]);
+ $address->province = $this->formatValue($vcard->ADR->getParts()[4]);
+ $address->postal_code = $this->formatValue($vcard->ADR->getParts()[5]);
$country = Country::where('country', $vcard->ADR->getParts()[6])
->orWhere('iso', strtolower($vcard->ADR->getParts()[6]))
->first();
if ($country) {
- $contact->country_id = $country->id;
+ $address->country_id = $country->id;
}
+
+ $address->contact_id = $contact->id;
+ $address->account_id = $contact->account_id;
+ $address->save();
}
- $contact->job = $this->formatValue($vcard->ORG);
+ if (! is_null($this->formatValue($vcard->EMAIL))) {
+ // Saves the email
+ $contactFieldType = ContactFieldType::where('type', 'email')->first();
+ $contactField = new ContactField;
+ $contactField->account_id = $contact->account_id;
+ $contactField->contact_id = $contact->id;
+ $contactField->data = $this->formatValue($vcard->EMAIL);
+ $contactField->contact_field_type_id = $contactFieldType->id;
+ $contactField->save();
+ }
- $contact->setAvatarColor();
-
- $contact->save();
+ if (! is_null($this->formatValue($vcard->TEL))) {
+ // Saves the phone number
+ $contactFieldType = ContactFieldType::where('type', 'phone')->first();
+ $contactField = new ContactField;
+ $contactField->account_id = $contact->account_id;
+ $contactField->contact_id = $contact->id;
+ $contactField->data = $this->formatValue($vcard->TEL);
+ $contactField->contact_field_type_id = $contactFieldType->id;
+ $contactField->save();
+ }
// if birthdate is known, we need to create reminders
if (! $contact->isBirthdateApproximate()) {
@@ -185,12 +212,22 @@ class AddContactFromVCard implements ShouldQueue
{
$email = (string) $vcard->EMAIL;
- $contact = Contact::where([
+ $contactFieldType = ContactFieldType::where([
['account_id', $account_id],
- ['email', $email],
+ ['type', 'email'],
])->first();
- return $email && $contact;
+ $contactField = null;
+
+ if ($contactFieldType) {
+ $contactField = ContactField::where([
+ ['account_id', $account_id],
+ ['data', $email],
+ ['contact_field_type_id', $contactFieldType->id],
+ ])->first();
+ }
+
+ return $email && $contactField;
}
private function fileImportJobReport(VCard $vcard, $status, $reason = null)
diff --git a/app/Jobs/ExportAccountAsSQL.php b/app/Jobs/ExportAccountAsSQL.php
index b4d382431..22ff45283 100644
--- a/app/Jobs/ExportAccountAsSQL.php
+++ b/app/Jobs/ExportAccountAsSQL.php
@@ -34,6 +34,8 @@ class ExportAccountAsSQL
'oauth_clients',
'oauth_personal_access_clients',
'oauth_refresh_tokens',
+ 'api_usage',
+ 'default_contact_field_types',
];
protected $ignoredColumns = [
diff --git a/app/Jobs/ResizeAvatars.php b/app/Jobs/ResizeAvatars.php
index ceed96915..4a6d0deec 100644
--- a/app/Jobs/ResizeAvatars.php
+++ b/app/Jobs/ResizeAvatars.php
@@ -35,10 +35,14 @@ class ResizeAvatars implements ShouldQueue
public function handle()
{
if ($this->contact->has_avatar == 'true') {
- $avatar_file = Storage::disk($this->contact->avatar_location)->get($this->contact->avatar_file_name);
- $avatar_path = Storage::disk($this->contact->avatar_location)->url($this->contact->avatar_file_name);
- $avatar_filename_without_extension = pathinfo($avatar_path, PATHINFO_FILENAME);
- $avatar_extension = pathinfo($avatar_path, PATHINFO_EXTENSION);
+ try {
+ $avatar_file = Storage::disk($this->contact->avatar_location)->get($this->contact->avatar_file_name);
+ $avatar_path = Storage::disk($this->contact->avatar_location)->url($this->contact->avatar_file_name);
+ $avatar_filename_without_extension = pathinfo($avatar_path, PATHINFO_FILENAME);
+ $avatar_extension = pathinfo($avatar_path, PATHINFO_EXTENSION);
+ } catch (FileNotFoundException $e) {
+ return;
+ }
$size = 110;
$avatar_cropped_path = 'avatars/'.$avatar_filename_without_extension.'_'.$size.'.'.$avatar_extension;
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index f0b8387c5..b06ae748b 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -15,10 +15,6 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
- View::composer(
- 'partials.components.country-select', 'App\Http\ViewComposers\CountrySelectViewComposer'
- );
-
View::composer(
'partials.components.currency-select', 'App\Http\ViewComposers\CurrencySelectViewComposer'
);
diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php
index ad5d8623b..629b86f27 100644
--- a/app/Providers/RouteServiceProvider.php
+++ b/app/Providers/RouteServiceProvider.php
@@ -11,6 +11,7 @@ use App\Contact;
use App\Activity;
use App\Reminder;
use App\Offspring;
+use App\ContactField;
use App\Relationship;
use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
@@ -41,6 +42,13 @@ class RouteServiceProvider extends ServiceProvider
->firstOrFail();
});
+ Route::bind('contactfield', function ($value, $route) {
+ return ContactField::where('account_id', auth()->user()->account_id)
+ ->where('contact_id', $route->parameter('contact')->id)
+ ->where('id', $value)
+ ->firstOrFail();
+ });
+
Route::bind('activity', function ($value, $route) {
return Activity::where('account_id', auth()->user()->account_id)
->where('id', $value)
diff --git a/composer.lock b/composer.lock
index 12477d834..cde6066b5 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "content-hash": "23ddf9eaafe1d1d25485868a3016425f",
+ "content-hash": "9692967b533183e31586508a19ddff6d",
"packages": [
{
"name": "aws/aws-sdk-php",
- "version": "3.36.34",
+ "version": "3.38.1",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
- "reference": "adc4e9928730cb65b9b7914084cbf1d8c988419a"
+ "reference": "9f704274f4748d2039a16d45b3388ed8dde74e89"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/adc4e9928730cb65b9b7914084cbf1d8c988419a",
- "reference": "adc4e9928730cb65b9b7914084cbf1d8c988419a",
+ "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/9f704274f4748d2039a16d45b3388ed8dde74e89",
+ "reference": "9f704274f4748d2039a16d45b3388ed8dde74e89",
"shasum": ""
},
"require": {
@@ -84,7 +84,7 @@
"s3",
"sdk"
],
- "time": "2017-10-26T20:45:00+00:00"
+ "time": "2017-11-09T19:15:59+00:00"
},
{
"name": "barryvdh/laravel-debugbar",
@@ -1366,16 +1366,16 @@
},
{
"name": "laravel/dusk",
- "version": "v1.1.0",
+ "version": "v1.1.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/dusk.git",
- "reference": "6b81e97ae1ce384e3d8dbd020b2b9751c1449889"
+ "reference": "87d57bbcb878e569aa8750e1d487ce923561f3e3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/dusk/zipball/6b81e97ae1ce384e3d8dbd020b2b9751c1449889",
- "reference": "6b81e97ae1ce384e3d8dbd020b2b9751c1449889",
+ "url": "https://api.github.com/repos/laravel/dusk/zipball/87d57bbcb878e569aa8750e1d487ce923561f3e3",
+ "reference": "87d57bbcb878e569aa8750e1d487ce923561f3e3",
"shasum": ""
},
"require": {
@@ -1394,7 +1394,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-master": "2.0-dev"
}
},
"autoload": {
@@ -1413,25 +1413,26 @@
}
],
"description": "Laravel Dusk provides simple end-to-end testing and browser automation.",
+ "homepage": "https://laravel.com",
"keywords": [
"laravel",
"testing",
"webdriver"
],
- "time": "2017-04-23T17:13:04+00:00"
+ "time": "2017-10-31T21:41:42+00:00"
},
{
"name": "laravel/framework",
- "version": "v5.5.19",
+ "version": "v5.5.20",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
- "reference": "c678100e84934ec85c9f8bc26bd0a60222682719"
+ "reference": "ce0019d22a83b1b240330ea4115ae27a4d75d79c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/framework/zipball/c678100e84934ec85c9f8bc26bd0a60222682719",
- "reference": "c678100e84934ec85c9f8bc26bd0a60222682719",
+ "url": "https://api.github.com/repos/laravel/framework/zipball/ce0019d22a83b1b240330ea4115ae27a4d75d79c",
+ "reference": "ce0019d22a83b1b240330ea4115ae27a4d75d79c",
"shasum": ""
},
"require": {
@@ -1513,7 +1514,7 @@
"nexmo/client": "Required to use the Nexmo transport (~1.0).",
"pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).",
"predis/predis": "Required to use the redis cache and queue drivers (~1.0).",
- "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).",
+ "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~3.0).",
"symfony/css-selector": "Required to use some of the crawler integration testing tools (~3.3).",
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (~3.3).",
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (~1.0)."
@@ -1549,7 +1550,7 @@
"framework",
"laravel"
],
- "time": "2017-10-25T19:10:45+00:00"
+ "time": "2017-11-07T14:24:50+00:00"
},
{
"name": "laravel/passport",
@@ -1622,16 +1623,16 @@
},
{
"name": "laravel/socialite",
- "version": "v3.0.7",
+ "version": "v3.0.9",
"source": {
"type": "git",
"url": "https://github.com/laravel/socialite.git",
- "reference": "d79174513dbf14359b53e44394cf71373ae03433"
+ "reference": "fc1c8d415699e502f3e61cbc61e3250d5bd942eb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/laravel/socialite/zipball/d79174513dbf14359b53e44394cf71373ae03433",
- "reference": "d79174513dbf14359b53e44394cf71373ae03433",
+ "url": "https://api.github.com/repos/laravel/socialite/zipball/fc1c8d415699e502f3e61cbc61e3250d5bd942eb",
+ "reference": "fc1c8d415699e502f3e61cbc61e3250d5bd942eb",
"shasum": ""
},
"require": {
@@ -1680,7 +1681,7 @@
"laravel",
"oauth"
],
- "time": "2017-07-22T14:44:37+00:00"
+ "time": "2017-11-06T16:02:48+00:00"
},
{
"name": "lcobucci/jwt",
@@ -2192,7 +2193,7 @@
},
{
"name": "mtdowling/cron-expression",
- "version": "v1.2.0",
+ "version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/mtdowling/cron-expression.git",
@@ -2891,12 +2892,12 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
- "reference": "9660ad3b85be3e3b90eacb9be3fcf7d12be60a90"
+ "reference": "5de810cf96008ab760a0590fb49078e12ab80cf9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9660ad3b85be3e3b90eacb9be3fcf7d12be60a90",
- "reference": "9660ad3b85be3e3b90eacb9be3fcf7d12be60a90",
+ "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5de810cf96008ab760a0590fb49078e12ab80cf9",
+ "reference": "5de810cf96008ab760a0590fb49078e12ab80cf9",
"shasum": ""
},
"conflict": {
@@ -2904,7 +2905,7 @@
"amphp/artax": ">=2,<2.0.6|<1.0.6",
"aws/aws-sdk-php": ">=3,<3.2.1",
"bugsnag/bugsnag-laravel": ">=2,<2.0.2",
- "cakephp/cakephp": ">=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=1.3,<1.3.18|>=3.1,<3.1.4",
+ "cakephp/cakephp": ">=2,<2.4.99|>=2.5,<2.5.99|>=2.6,<2.6.12|>=2.7,<2.7.6|>=3,<3.0.15|>=3.1,<3.1.4|>=1.3,<1.3.18",
"cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4",
"cartalyst/sentry": "<2.1",
"codeigniter/framework": "<=3.0.6",
@@ -2924,7 +2925,7 @@
"dompdf/dompdf": ">=0.6,<0.6.2",
"drupal/core": ">=8,<8.3.7",
"drupal/drupal": ">=8,<8.3.7",
- "ezsystems/ezpublish-legacy": ">=5.4,<5.4.10.1|>=5.3,<5.3.12.2|>=2017.8,<2017.8.1.1",
+ "ezsystems/ezpublish-legacy": ">=2017.8,<2017.8.1.1|>=5.4,<5.4.10.1|>=5.3,<5.3.12.2",
"firebase/php-jwt": "<2",
"friendsofsymfony/rest-bundle": ">=1.2,<1.2.2",
"friendsofsymfony/user-bundle": ">=1.2,<1.3.5",
@@ -2944,6 +2945,7 @@
"oro/crm": ">=1.7,<1.7.4",
"oro/platform": ">=1.7,<1.7.4",
"phpmailer/phpmailer": ">=5,<5.2.24",
+ "phpunit/phpunit": ">=5.0.10,<5.6.3|>=4.8.19,<4.8.28",
"phpxmlrpc/extras": "<6.0.1",
"pusher/pusher-php-server": "<2.2.1",
"sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9",
@@ -2964,8 +2966,8 @@
"symfony/http-foundation": ">=2,<2.3.27|>=2.4,<2.5.11|>=2.6,<2.6.6",
"symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8",
"symfony/routing": ">=2,<2.0.19",
- "symfony/security": ">=2.3,<2.3.37|>=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5|>=2,<2.0.25|>=2.1,<2.1.13|>=2.2,<2.2.9",
- "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5|>=2.8,<2.8.6|>=3,<3.0.6",
+ "symfony/security": ">=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5|>=2,<2.0.25|>=2.3,<2.3.37|>=2.4,<2.6.13|>=2.7,<2.7.9|>=2.1,<2.1.13|>=2.2,<2.2.9",
+ "symfony/security-core": ">=2.8,<2.8.6|>=3,<3.0.6|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5|>=2.4,<2.6.13|>=2.7,<2.7.9",
"symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.13|>=2.8,<2.8.6|>=3,<3.0.6",
"symfony/serializer": ">=2,<2.0.11",
"symfony/symfony": ">=2,<2.3.41|>=2.4,<2.7.13|>=2.8,<2.8.6|>=3,<3.0.6|>=2.7.30,<2.7.32|>=2.8.23,<2.8.25|>=3.2.10,<3.2.12|>=3.3.3,<3.3.5",
@@ -2974,11 +2976,11 @@
"symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4",
"symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7",
"thelia/backoffice-default-template": ">=2.1,<2.1.2",
- "thelia/thelia": ">=2.1,<2.1.2|>=2.1.0-beta1,<2.1.3",
+ "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2",
"twig/twig": "<1.20",
- "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.22|>=8,<8.7.5",
- "typo3/flow": ">=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5|>=1,<1.0.4",
- "typo3/neos": ">=1.2,<1.2.13|>=2,<2.0.4|>=1.1,<1.1.3",
+ "typo3/cms": ">=8,<8.7.5|>=7,<7.6.22|>=6.2,<6.2.30",
+ "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5",
+ "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4",
"willdurand/js-translation-bundle": "<2.1.1",
"yiisoft/yii": ">=1.1.14,<1.1.15",
"yiisoft/yii2": "<2.0.5",
@@ -3022,7 +3024,7 @@
}
],
"description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it",
- "time": "2017-10-29T18:43:15+00:00"
+ "time": "2017-11-11T03:27:01+00:00"
},
{
"name": "sabberworm/php-css-parser",
@@ -3281,16 +3283,16 @@
},
{
"name": "sentry/sentry",
- "version": "1.8.0",
+ "version": "1.8.1",
"source": {
"type": "git",
"url": "https://github.com/getsentry/sentry-php.git",
- "reference": "b3a03c1eb2877f0c66885641a52216dcbf313a11"
+ "reference": "3e4bb1486cd4e09869cb3342aef374788d540f1c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/b3a03c1eb2877f0c66885641a52216dcbf313a11",
- "reference": "b3a03c1eb2877f0c66885641a52216dcbf313a11",
+ "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/3e4bb1486cd4e09869cb3342aef374788d540f1c",
+ "reference": "3e4bb1486cd4e09869cb3342aef374788d540f1c",
"shasum": ""
},
"require": {
@@ -3317,7 +3319,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.8.x-dev"
+ "dev-master": "1.9.x-dev"
}
},
"autoload": {
@@ -3341,7 +3343,7 @@
"log",
"logging"
],
- "time": "2017-10-29T21:19:48+00:00"
+ "time": "2017-11-09T17:44:23+00:00"
},
{
"name": "sentry/sentry-laravel",
@@ -3399,16 +3401,16 @@
},
{
"name": "stripe/stripe-php",
- "version": "v5.5.0",
+ "version": "v5.6.0",
"source": {
"type": "git",
"url": "https://github.com/stripe/stripe-php.git",
- "reference": "a523748f2db82beacfac7b22e0642e326aa3be64"
+ "reference": "0922533c9db11292c7a0aeafc27638f8f31b7fb6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/stripe/stripe-php/zipball/a523748f2db82beacfac7b22e0642e326aa3be64",
- "reference": "a523748f2db82beacfac7b22e0642e326aa3be64",
+ "url": "https://api.github.com/repos/stripe/stripe-php/zipball/0922533c9db11292c7a0aeafc27638f8f31b7fb6",
+ "reference": "0922533c9db11292c7a0aeafc27638f8f31b7fb6",
"shasum": ""
},
"require": {
@@ -3450,7 +3452,7 @@
"payment processing",
"stripe"
],
- "time": "2017-10-27T16:27:13+00:00"
+ "time": "2017-10-31T18:52:25+00:00"
},
{
"name": "swiftmailer/swiftmailer",
@@ -3509,16 +3511,16 @@
},
{
"name": "symfony/console",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "116bc56e45a8e5572e51eb43ab58c769a352366c"
+ "reference": "fd684d68f83568d8293564b4971928a2c4bdfc5c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/116bc56e45a8e5572e51eb43ab58c769a352366c",
- "reference": "116bc56e45a8e5572e51eb43ab58c769a352366c",
+ "url": "https://api.github.com/repos/symfony/console/zipball/fd684d68f83568d8293564b4971928a2c4bdfc5c",
+ "reference": "fd684d68f83568d8293564b4971928a2c4bdfc5c",
"shasum": ""
},
"require": {
@@ -3573,7 +3575,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-07T14:16:22+00:00"
},
{
"name": "symfony/css-selector",
@@ -3630,16 +3632,16 @@
},
{
"name": "symfony/debug",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "eb95d9ce8f18dcc1b3dfff00cb624c402be78ffd"
+ "reference": "74557880e2846b5c84029faa96b834da37e29810"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/eb95d9ce8f18dcc1b3dfff00cb624c402be78ffd",
- "reference": "eb95d9ce8f18dcc1b3dfff00cb624c402be78ffd",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/74557880e2846b5c84029faa96b834da37e29810",
+ "reference": "74557880e2846b5c84029faa96b834da37e29810",
"shasum": ""
},
"require": {
@@ -3682,20 +3684,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-10T16:38:39+00:00"
},
{
"name": "symfony/event-dispatcher",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "d7ba037e4b8221956ab1e221c73c9e27e05dd423"
+ "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d7ba037e4b8221956ab1e221c73c9e27e05dd423",
- "reference": "d7ba037e4b8221956ab1e221c73c9e27e05dd423",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/271d8c27c3ec5ecee6e2ac06016232e249d638d9",
+ "reference": "271d8c27c3ec5ecee6e2ac06016232e249d638d9",
"shasum": ""
},
"require": {
@@ -3745,20 +3747,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
"name": "symfony/finder",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "773e19a491d97926f236942484cb541560ce862d"
+ "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/773e19a491d97926f236942484cb541560ce862d",
- "reference": "773e19a491d97926f236942484cb541560ce862d",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
+ "reference": "138af5ec075d4b1d1bd19de08c38a34bb2d7d880",
"shasum": ""
},
"require": {
@@ -3794,20 +3796,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
"name": "symfony/http-foundation",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "22cf9c2b1d9f67cc8e75ae7f4eaa60e4c1eff1f8"
+ "reference": "873ccdf8c1cae20da0184862820c434e20fdc8ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/22cf9c2b1d9f67cc8e75ae7f4eaa60e4c1eff1f8",
- "reference": "22cf9c2b1d9f67cc8e75ae7f4eaa60e4c1eff1f8",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/873ccdf8c1cae20da0184862820c434e20fdc8ce",
+ "reference": "873ccdf8c1cae20da0184862820c434e20fdc8ce",
"shasum": ""
},
"require": {
@@ -3847,20 +3849,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
- "time": "2017-10-05T23:10:23+00:00"
+ "time": "2017-11-05T19:07:00+00:00"
},
{
"name": "symfony/http-kernel",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "654f047a78756964bf91b619554f956517394018"
+ "reference": "f38c96b8d88a37b4f6bc8ae46a48b018d4894dd0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/654f047a78756964bf91b619554f956517394018",
- "reference": "654f047a78756964bf91b619554f956517394018",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f38c96b8d88a37b4f6bc8ae46a48b018d4894dd0",
+ "reference": "f38c96b8d88a37b4f6bc8ae46a48b018d4894dd0",
"shasum": ""
},
"require": {
@@ -3868,7 +3870,7 @@
"psr/log": "~1.0",
"symfony/debug": "~2.8|~3.0",
"symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/http-foundation": "~3.3"
+ "symfony/http-foundation": "^3.3.11"
},
"conflict": {
"symfony/config": "<2.8",
@@ -3933,7 +3935,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
- "time": "2017-10-05T23:40:19+00:00"
+ "time": "2017-11-10T20:08:13+00:00"
},
{
"name": "symfony/polyfill-mbstring",
@@ -3996,16 +3998,16 @@
},
{
"name": "symfony/process",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "fdf89e57a723a29baf536e288d6e232c059697b1"
+ "reference": "e14bb64d7559e6923fb13ee3b3d8fa763a2c0930"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/fdf89e57a723a29baf536e288d6e232c059697b1",
- "reference": "fdf89e57a723a29baf536e288d6e232c059697b1",
+ "url": "https://api.github.com/repos/symfony/process/zipball/e14bb64d7559e6923fb13ee3b3d8fa763a2c0930",
+ "reference": "e14bb64d7559e6923fb13ee3b3d8fa763a2c0930",
"shasum": ""
},
"require": {
@@ -4041,7 +4043,7 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-05T15:47:03+00:00"
},
{
"name": "symfony/psr-http-message-bridge",
@@ -4105,16 +4107,16 @@
},
{
"name": "symfony/routing",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "2e26fa63da029dab49bf9377b3b4f60a8fecb009"
+ "reference": "cf7fa1dfcfee2c96969bfa1c0341e5627ecb1e95"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/2e26fa63da029dab49bf9377b3b4f60a8fecb009",
- "reference": "2e26fa63da029dab49bf9377b3b4f60a8fecb009",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/cf7fa1dfcfee2c96969bfa1c0341e5627ecb1e95",
+ "reference": "cf7fa1dfcfee2c96969bfa1c0341e5627ecb1e95",
"shasum": ""
},
"require": {
@@ -4179,20 +4181,20 @@
"uri",
"url"
],
- "time": "2017-10-02T07:25:00+00:00"
+ "time": "2017-11-07T14:16:22+00:00"
},
{
"name": "symfony/translation",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "409bf229cd552bf7e3faa8ab7e3980b07672073f"
+ "reference": "373e553477e55cd08f8b86b74db766c75b987fdb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/409bf229cd552bf7e3faa8ab7e3980b07672073f",
- "reference": "409bf229cd552bf7e3faa8ab7e3980b07672073f",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/373e553477e55cd08f8b86b74db766c75b987fdb",
+ "reference": "373e553477e55cd08f8b86b74db766c75b987fdb",
"shasum": ""
},
"require": {
@@ -4244,20 +4246,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-07T14:12:55+00:00"
},
{
"name": "symfony/var-dumper",
- "version": "v3.3.10",
+ "version": "v3.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
- "reference": "03e3693a36701f1c581dd24a6d6eea2eba2113f6"
+ "reference": "805de6bd6869073e60610df1b14ab7d969c61b01"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/03e3693a36701f1c581dd24a6d6eea2eba2113f6",
- "reference": "03e3693a36701f1c581dd24a6d6eea2eba2113f6",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/805de6bd6869073e60610df1b14ab7d969c61b01",
+ "reference": "805de6bd6869073e60610df1b14ab7d969c61b01",
"shasum": ""
},
"require": {
@@ -4312,7 +4314,7 @@
"debug",
"dump"
],
- "time": "2017-10-02T06:42:24+00:00"
+ "time": "2017-11-07T14:16:22+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -5048,16 +5050,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "5.2.2",
+ "version": "5.2.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b"
+ "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8ed1902a57849e117b5651fc1a5c48110946c06b",
- "reference": "8ed1902a57849e117b5651fc1a5c48110946c06b",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d",
+ "reference": "8e1d2397d8adf59a3f12b2878a3aaa66d1ab189d",
"shasum": ""
},
"require": {
@@ -5066,7 +5068,7 @@
"php": "^7.0",
"phpunit/php-file-iterator": "^1.4.2",
"phpunit/php-text-template": "^1.2.1",
- "phpunit/php-token-stream": "^1.4.11 || ^2.0",
+ "phpunit/php-token-stream": "^2.0",
"sebastian/code-unit-reverse-lookup": "^1.0.1",
"sebastian/environment": "^3.0",
"sebastian/version": "^2.0.1",
@@ -5108,7 +5110,7 @@
"testing",
"xunit"
],
- "time": "2017-08-03T12:40:43+00:00"
+ "time": "2017-11-03T13:47:33+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -5298,16 +5300,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "6.4.3",
+ "version": "6.4.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13"
+ "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/06b28548fd2b4a20c3cd6e247dc86331a7d4db13",
- "reference": "06b28548fd2b4a20c3cd6e247dc86331a7d4db13",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/562f7dc75d46510a4ed5d16189ae57fbe45a9932",
+ "reference": "562f7dc75d46510a4ed5d16189ae57fbe45a9932",
"shasum": ""
},
"require": {
@@ -5378,7 +5380,7 @@
"testing",
"xunit"
],
- "time": "2017-10-16T13:18:59+00:00"
+ "time": "2017-11-08T11:26:09+00:00"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -5486,30 +5488,30 @@
},
{
"name": "sebastian/comparator",
- "version": "2.0.2",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a"
+ "reference": "1174d9018191e93cb9d719edec01257fc05f8158"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/ae068fede81d06e7bb9bb46a367210a3d3e1fe6a",
- "reference": "ae068fede81d06e7bb9bb46a367210a3d3e1fe6a",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1174d9018191e93cb9d719edec01257fc05f8158",
+ "reference": "1174d9018191e93cb9d719edec01257fc05f8158",
"shasum": ""
},
"require": {
"php": "^7.0",
"sebastian/diff": "^2.0",
- "sebastian/exporter": "^3.0"
+ "sebastian/exporter": "^3.1"
},
"require-dev": {
- "phpunit/phpunit": "^6.0"
+ "phpunit/phpunit": "^6.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0.x-dev"
+ "dev-master": "2.1.x-dev"
}
},
"autoload": {
@@ -5540,13 +5542,13 @@
}
],
"description": "Provides the functionality to compare PHP values for equality",
- "homepage": "http://www.github.com/sebastianbergmann/comparator",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
"equality"
],
- "time": "2017-08-03T07:14:59+00:00"
+ "time": "2017-11-03T07:16:52+00:00"
},
{
"name": "sebastian/diff",
@@ -6153,7 +6155,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.0",
+ "php": "^7.1",
"ext-intl": "*"
},
"platform-dev": []
diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
index d7bdebfc4..461de4475 100644
--- a/database/factories/ModelFactory.php
+++ b/database/factories/ModelFactory.php
@@ -136,3 +136,9 @@ $factory->define(App\Invitation::class, function (Faker\Generator $faker) {
'account_id' => 1,
];
});
+
+$factory->define(App\Address::class, function (Faker\Generator $faker) {
+ return [
+ 'account_id' => 1,
+ ];
+});
diff --git a/database/migrations/2017_11_10_174654_create_contact_fields_table.php b/database/migrations/2017_11_10_174654_create_contact_fields_table.php
new file mode 100644
index 000000000..81a658867
--- /dev/null
+++ b/database/migrations/2017_11_10_174654_create_contact_fields_table.php
@@ -0,0 +1,106 @@
+increments('id');
+ $table->integer('account_id')->unsigned();
+ $table->string('name');
+ $table->string('fontawesome_icon')->nullable();
+ $table->string('protocol')->nullable();
+ $table->boolean('delible')->default(1);
+ $table->string('type')->nullable();
+ $table->timestamps();
+
+ $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
+ });
+
+ Schema::create('contact_fields', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('account_id')->unsigned();
+ $table->integer('contact_id')->unsigned();
+ $table->integer('contact_field_type_id')->unsigned();
+ $table->string('data');
+ $table->timestamps();
+
+ $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
+ $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
+ $table->foreign('contact_field_type_id')->references('id')->on('contact_field_types')->onDelete('cascade');
+ });
+
+ Schema::create('addresses', function (Blueprint $table) {
+ $table->increments('id');
+ $table->integer('account_id')->unsigned();
+ $table->integer('contact_id')->unsigned();
+ $table->string('name')->nullable();
+ $table->string('street')->nullable();
+ $table->string('city')->nullable();
+ $table->string('province')->nullable();
+ $table->string('postal_code')->nullable();
+ $table->integer('country_id')->nullable();
+ $table->timestamps();
+
+ $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
+ $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
+ });
+
+ Schema::create('default_contact_field_types', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('name');
+ $table->string('fontawesome_icon')->nullable();
+ $table->string('protocol')->nullable();
+ $table->boolean('migrated')->default(0);
+ $table->boolean('delible')->default(1);
+ $table->string('type')->nullable();
+ $table->timestamps();
+ });
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Email',
+ 'fontawesome_icon' => 'fa fa-envelope-open-o',
+ 'protocol' => 'mailto:',
+ 'delible' => false,
+ 'type' => 'email',
+ ]);
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Phone',
+ 'fontawesome_icon' => 'fa fa-volume-control-phone',
+ 'protocol' => 'tel:',
+ 'delible' => false,
+ 'type' => 'phone',
+ ]);
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Facebook',
+ 'fontawesome_icon' => 'fa fa-facebook-official',
+ ]);
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Twitter',
+ 'fontawesome_icon' => 'fa fa-twitter-square',
+ ]);
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Whatsapp',
+ 'fontawesome_icon' => 'fa fa-whatsapp',
+ ]);
+
+ $id = DB::table('default_contact_field_types')->insertGetId([
+ 'name' => 'Telegram',
+ 'fontawesome_icon' => 'fa fa-telegram',
+ 'protocol' => 'telegram:',
+ ]);
+ }
+}
diff --git a/database/migrations/2017_11_10_181043_migrate_contacts_information.php b/database/migrations/2017_11_10_181043_migrate_contacts_information.php
new file mode 100644
index 000000000..b3b4a25d6
--- /dev/null
+++ b/database/migrations/2017_11_10_181043_migrate_contacts_information.php
@@ -0,0 +1,92 @@
+get();
+
+ foreach ($accounts as $account) {
+ $contacts = DB::table('contacts')->where('account_id', $account->id)->get();
+
+ $account->populateContactFieldTypeTable();
+
+ // EMAIL
+ $emailId = DB::table('contact_field_types')->where('account_id', $account->id)
+ ->where('type', 'email')
+ ->first();
+
+ // PHONE NUMBER
+ $idPhoneNumber = DB::table('contact_field_types')->where('account_id', $account->id)
+ ->where('type', 'phone')
+ ->first();
+
+ // FACEBOOK
+ $idFacebook = DB::table('contact_field_types')->where('account_id', $account->id)
+ ->where('name', 'Facebook')
+ ->first();
+
+ // TWITTER
+ $idTwitter = DB::table('contact_field_types')->where('account_id', $account->id)
+ ->where('name', 'Twitter')
+ ->first();
+
+ foreach ($contacts as $contact) {
+ if (! is_null($contact->email)) {
+ DB::table('contact_fields')->insert([
+ 'account_id' => $account->id,
+ 'contact_id' => $contact->id,
+ 'contact_field_type_id' => $emailId->id,
+ 'data' => $contact->email,
+ 'created_at' => \Carbon\Carbon::now(),
+ ]);
+ }
+
+ if (! is_null($contact->phone_number)) {
+ DB::table('contact_fields')->insert([
+ 'account_id' => $account->id,
+ 'contact_id' => $contact->id,
+ 'contact_field_type_id' => $idPhoneNumber->id,
+ 'data' => $contact->phone_number,
+ 'created_at' => \Carbon\Carbon::now(),
+ ]);
+ }
+
+ if (! is_null($contact->facebook_profile_url)) {
+ DB::table('contact_fields')->insert([
+ 'account_id' => $account->id,
+ 'contact_id' => $contact->id,
+ 'contact_field_type_id' => $idFacebook->id,
+ 'data' => $contact->facebook_profile_url,
+ 'created_at' => \Carbon\Carbon::now(),
+ ]);
+ }
+
+ if (! is_null($contact->twitter_profile_url)) {
+ DB::table('contact_fields')->insert([
+ 'account_id' => $account->id,
+ 'contact_id' => $contact->id,
+ 'contact_field_type_id' => $idTwitter->id,
+ 'data' => $contact->twitter_profile_url,
+ 'created_at' => \Carbon\Carbon::now(),
+ ]);
+ }
+ }
+
+ \Log::info('ACCOUNT PASSED: '.$account->id);
+ }
+
+ $instance = Instance::first();
+ $instance->markDefaultContactFieldTypeAsMigrated();
+ \Log::info('PASSED');
+ }
+}
diff --git a/database/migrations/2017_11_10_202620_move_addresses_from_contact_to_addresses.php b/database/migrations/2017_11_10_202620_move_addresses_from_contact_to_addresses.php
new file mode 100644
index 000000000..81c598cec
--- /dev/null
+++ b/database/migrations/2017_11_10_202620_move_addresses_from_contact_to_addresses.php
@@ -0,0 +1,30 @@
+select('account_id', 'id', 'street', 'city', 'province', 'postal_code', 'country_id')->get();
+ foreach ($contacts as $contact) {
+ if (! is_null($contact->street) or ! is_null($contact->city) or ! is_null($contact->province) or ! is_null($contact->postal_code) or ! is_null($contact->country_id)) {
+ $id = DB::table('addresses')->insertGetId([
+ 'account_id' => $contact->account_id,
+ 'contact_id' => $contact->id,
+ 'name' => 'default',
+ 'street' => (is_null($contact->street) ? null : $contact->street),
+ 'city' => (is_null($contact->city) ? null : $contact->city),
+ 'province' => (is_null($contact->province) ? null : $contact->province),
+ 'postal_code' => (is_null($contact->postal_code) ? null : $contact->postal_code),
+ 'country_id' => (is_null($contact->country_id) ? null : $contact->country_id),
+ ]);
+ }
+ }
+ }
+}
diff --git a/database/migrations/2017_11_10_204035_delete_contact_fields_from_contacts.php b/database/migrations/2017_11_10_204035_delete_contact_fields_from_contacts.php
new file mode 100644
index 000000000..e3edf2da0
--- /dev/null
+++ b/database/migrations/2017_11_10_204035_delete_contact_fields_from_contacts.php
@@ -0,0 +1,29 @@
+dropIndex('unique_for_each_account_email_pair');
+ $table->dropColumn('email');
+ $table->dropColumn('phone_number');
+ $table->dropColumn('street');
+ $table->dropColumn('city');
+ $table->dropColumn('province');
+ $table->dropColumn('postal_code');
+ $table->dropColumn('country_id');
+ $table->dropColumn('facebook_profile_url');
+ $table->dropColumn('twitter_profile_url');
+ });
+ }
+}
diff --git a/database/seeds/FakeContentTableSeeder.php b/database/seeds/FakeContentTableSeeder.php
index 540f73cff..c341d482c 100644
--- a/database/seeds/FakeContentTableSeeder.php
+++ b/database/seeds/FakeContentTableSeeder.php
@@ -1,5 +1,6 @@
str_random(30),
]);
+ $account = Account::find($accountID);
+ $account->populateContactFieldTypeTable();
+
// populate user table
$userId = DB::table('users')->insertGetId([
'account_id' => $accountID,
@@ -59,25 +63,6 @@ class FakeContentTableSeeder extends Seeder
$contact = Contact::find($contactID);
$contact->setAvatarColor();
- // add email
- if (rand(1, 2) == 1) {
- $contact->email = $faker->email;
- }
-
- // add phonenumber
- if (rand(1, 2) == 1) {
- $contact->phone_number = $faker->phoneNumber;
- }
-
- // add address
- if (rand(1, 2) == 1) {
- $contact->street = $faker->streetAddress;
- $contact->postal_code = $faker->postcode;
- $contact->province = $faker->state;
- $contact->city = $faker->city;
- $countryID = '1';
- }
-
// add food preferencies
if (rand(1, 2) == 1) {
$contact->food_preferencies = $faker->realText();
diff --git a/docs/contribute/contribute.md b/docs/contribute/contribute.md
index b781a2ab8..0e3cef553 100644
--- a/docs/contribute/contribute.md
+++ b/docs/contribute/contribute.md
@@ -90,13 +90,21 @@ the application. To compile those front-end assets, use `npm run dev`.
To monitor changes and compile assets on the fly, use `npm run watch`.
-#### Bootstrap 4
+#### CSS
-At the current time, we are using Bootstrap 4 Alpha 2. Not everything though -
-we do use only what we need. I would have wanted to use something completely
-custom, but why reinvent the wheel? Anyway, make sure you don't update this
-dependency with Bower. If you do, make sure that everything is thoroughly tested
-as when Bootstrap changes version, a lot of changes are introduced.
+At the current time, we are using a mix of Bootstrap 4 and [Tachyons](https://tachyons.io).
+We aim to use a maximum of [Atomic CSS](https://adamwathan.me/css-utility-classes-and-separation-of-concerns/)
+in place of having bloated, super hard to maintain CSS files. This is why,
+over time, we'll get rid of Bootstrap entirely.
+
+#### JS and Vue
+
+We are also using [Vue.js](https://vuejs.org/) in some places of the
+application, and we'll use it more and more over time. Vue is very simple to
+learn and use, and with [Vue Components](https://vuejs.org/v2/guide/components.html),
+we can easily create isolated, reusable components in the app. If you want to
+add a new feature, you don't need to use Vue.js - you can use plain HTML views
+served by the backend. But with Vue.js, it'll be a nicer experience.
### Backend
diff --git a/public/js/app.js b/public/js/app.js
index 39829f477..07edeec7c 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -2432,6 +2432,838 @@ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol
/***/ }),
+/***/ "./node_modules/babel-loader/lib/index.js?{\"cacheDirectory\":true,\"presets\":[[\"env\",{\"modules\":false,\"targets\":{\"browsers\":[\"> 2%\"],\"uglify\":true}}]],\"plugins\":[\"transform-object-rest-spread\"]}!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./resources/assets/js/components/people/Addresses.vue":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+var _methods;
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+/* harmony default export */ __webpack_exports__["default"] = ({
+ /*
+ * The component's data.
+ */
+ data: function data() {
+ return {
+ contactAddresses: [],
+ countries: [],
+
+ editMode: false,
+ addMode: false,
+
+ createForm: {
+ country_id: 0,
+ name: '',
+ street: '',
+ city: '',
+ province: '',
+ postal_code: ''
+ },
+
+ updateForm: {
+ id: '',
+ country_id: 0,
+ name: '',
+ street: '',
+ city: '',
+ province: '',
+ postal_code: ''
+ }
+ };
+ },
+
+
+ /**
+ * Prepare the component (Vue 1.x).
+ */
+ ready: function ready() {
+ this.prepareComponent();
+ },
+
+
+ /**
+ * Prepare the component (Vue 2.x).
+ */
+ mounted: function mounted() {
+ this.prepareComponent();
+ },
+
+
+ props: ['contactId'],
+
+ methods: (_methods = {
+ /**
+ * Prepare the component.
+ */
+ prepareComponent: function prepareComponent() {
+ this.getAddresses();
+ this.getCountries();
+ },
+ getAddresses: function getAddresses() {
+ var _this = this;
+
+ axios.get('/people/' + this.contactId + '/addresses').then(function (response) {
+ _this.contactAddresses = response.data;
+ });
+ },
+ getCountries: function getCountries() {
+ var _this2 = this;
+
+ axios.get('/people/' + this.contactId + '/countries').then(function (response) {
+ _this2.countries = response.data;
+ });
+ },
+ store: function store() {
+ this.persistClient('post', '/people/' + this.contactId + '/contactfield', this.createForm);
+
+ this.addMode = false;
+ },
+ reinitialize: function reinitialize() {
+ this.createForm.country_id = '';
+ this.createForm.name = '';
+ this.createForm.street = '';
+ this.createForm.city = '';
+ this.createForm.province = '';
+ this.createForm.postal_code = '';
+ },
+ toggleAdd: function toggleAdd() {
+ this.addMode = true;
+ this.reinitialize();
+ },
+ toggleEdit: function toggleEdit(contactAddress) {
+ Vue.set(contactAddress, 'edit', !contactAddress.edit);
+ this.updateForm.id = contactAddress.id;
+ this.updateForm.country_id = contactAddress.country_id;
+ this.updateForm.name = contactAddress.name;
+ this.updateForm.street = contactAddress.street;
+ this.updateForm.city = contactAddress.city;
+ this.updateForm.province = contactAddress.province;
+ this.updateForm.postal_code = contactAddress.postal_code;
+ }
+ }, _defineProperty(_methods, 'store', function store() {
+ this.persistClient('post', '/people/' + this.contactId + '/addresses', this.createForm);
+
+ this.addMode = false;
+ }), _defineProperty(_methods, 'update', function update(contactAddress) {
+ this.persistClient('put', '/people/' + this.contactId + '/addresses/' + contactAddress.id, this.updateForm);
+ }), _defineProperty(_methods, 'trash', function trash(contactAddress) {
+ this.updateForm.id = contactAddress.id;
+
+ this.persistClient('delete', '/people/' + this.contactId + '/addresses/' + contactAddress.id, this.updateForm);
+
+ if (this.contactAddresses.length <= 1) {
+ this.editMode = false;
+ }
+ }), _defineProperty(_methods, 'persistClient', function persistClient(method, uri, form) {
+ var _this3 = this;
+
+ form.errors = {};
+
+ axios[method](uri, form).then(function (response) {
+ _this3.getAddresses();
+ }).catch(function (error) {
+ if (_typeof(error.response.data) === 'object') {
+ form.errors = _.flatten(_.toArray(error.response.data));
+ } else {
+ form.errors = ['Something went wrong. Please try again.'];
+ }
+ });
+ }), _methods)
+});
+
+/***/ }),
+
+/***/ "./node_modules/babel-loader/lib/index.js?{\"cacheDirectory\":true,\"presets\":[[\"env\",{\"modules\":false,\"targets\":{\"browsers\":[\"> 2%\"],\"uglify\":true}}]],\"plugins\":[\"transform-object-rest-spread\"]}!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./resources/assets/js/components/people/ContactInformation.vue":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+/* harmony default export */ __webpack_exports__["default"] = ({
+ /*
+ * The component's data.
+ */
+ data: function data() {
+ return {
+ contactInformationData: [],
+ contactFieldTypes: [],
+
+ editMode: false,
+ addMode: false,
+ updateMode: false,
+
+ createForm: {
+ contact_field_type_id: '',
+ data: '',
+ errors: []
+ },
+
+ updateForm: {
+ id: '',
+ contact_field_type_id: '',
+ data: '',
+ edit: false,
+ errors: []
+ }
+ };
+ },
+
+
+ /**
+ * Prepare the component (Vue 1.x).
+ */
+ ready: function ready() {
+ this.prepareComponent();
+ },
+
+
+ /**
+ * Prepare the component (Vue 2.x).
+ */
+ mounted: function mounted() {
+ this.prepareComponent();
+ },
+
+
+ props: ['contactId'],
+
+ methods: {
+ /**
+ * Prepare the component.
+ */
+ prepareComponent: function prepareComponent() {
+ this.getContactInformationData();
+ this.getContactFieldTypes();
+ },
+ getContactInformationData: function getContactInformationData() {
+ var _this = this;
+
+ axios.get('/people/' + this.contactId + '/contactfield').then(function (response) {
+ _this.contactInformationData = response.data;
+ });
+ },
+ getContactFieldTypes: function getContactFieldTypes() {
+ var _this2 = this;
+
+ axios.get('/people/' + this.contactId + '/contactfieldtypes').then(function (response) {
+ _this2.contactFieldTypes = response.data;
+ });
+ },
+ store: function store() {
+ this.persistClient('post', '/people/' + this.contactId + '/contactfield', this.createForm);
+
+ this.addMode = false;
+ },
+ toggleAdd: function toggleAdd() {
+ this.addMode = true;
+ this.createForm.data = '';
+ this.createForm.contact_field_type_id = '';
+ },
+ toggleEdit: function toggleEdit(contactField) {
+ Vue.set(contactField, 'edit', !contactField.edit);
+ this.updateForm.id = contactField.id;
+ this.updateForm.data = contactField.data;
+ this.updateForm.contact_field_type_id = contactField.contact_field_type_id;
+ },
+ update: function update(contactField) {
+ this.persistClient('put', '/people/' + this.contactId + '/contactfield/' + contactField.id, this.updateForm);
+ },
+ trash: function trash(contactField) {
+ this.updateForm.id = contactField.id;
+
+ this.persistClient('delete', '/people/' + this.contactId + '/contactfield/' + contactField.id, this.updateForm);
+
+ if (this.contactInformationData.length <= 1) {
+ this.editMode = false;
+ }
+ },
+ persistClient: function persistClient(method, uri, form) {
+ var _this3 = this;
+
+ form.errors = {};
+
+ axios[method](uri, form).then(function (response) {
+ _this3.getContactInformationData();
+ }).catch(function (error) {
+ if (_typeof(error.response.data) === 'object') {
+ form.errors = _.flatten(_.toArray(error.response.data));
+ } else {
+ form.errors = ['Something went wrong. Please try again.'];
+ }
+ });
+ }
+ }
+});
+
+/***/ }),
+
+/***/ "./node_modules/babel-loader/lib/index.js?{\"cacheDirectory\":true,\"presets\":[[\"env\",{\"modules\":false,\"targets\":{\"browsers\":[\"> 2%\"],\"uglify\":true}}]],\"plugins\":[\"transform-object-rest-spread\"]}!./node_modules/vue-loader/lib/selector.js?type=script&index=0&bustCache!./resources/assets/js/components/settings/ContactFieldTypes.vue":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+//
+
+/* harmony default export */ __webpack_exports__["default"] = ({
+ /*
+ * The component's data.
+ */
+ data: function data() {
+ return {
+ contactFieldTypes: [],
+
+ submitted: false,
+ edited: false,
+ deleted: false,
+
+ createForm: {
+ name: '',
+ protocol: '',
+ icon: '',
+ errors: []
+ },
+
+ editForm: {
+ id: '',
+ name: '',
+ protocol: '',
+ icon: '',
+ errors: []
+ }
+ };
+ },
+
+
+ /**
+ * Prepare the component (Vue 1.x).
+ */
+ ready: function ready() {
+ this.prepareComponent();
+ },
+
+
+ /**
+ * Prepare the component (Vue 2.x).
+ */
+ mounted: function mounted() {
+ this.prepareComponent();
+ },
+
+
+ methods: {
+ /**
+ * Prepare the component.
+ */
+ prepareComponent: function prepareComponent() {
+ this.getContactFieldTypes();
+
+ $('#modal-create-contact-field-type').on('shown.bs.modal', function () {
+ $('#name').focus();
+ });
+
+ $('#modal-edit-contact-field-type').on('shown.bs.modal', function () {
+ $('#name').focus();
+ });
+ },
+ getContactFieldTypes: function getContactFieldTypes() {
+ var _this = this;
+
+ axios.get('/settings/personalization/contactfieldtypes/').then(function (response) {
+ _this.contactFieldTypes = response.data;
+ });
+ },
+ add: function add() {
+ $('#modal-create-contact-field-type').modal('show');
+ },
+ store: function store() {
+ this.persistClient('post', '/settings/personalization/contactfieldtypes', this.createForm, '#modal-create-contact-field-type', this.submitted);
+ },
+ edit: function edit(contactFieldType) {
+ this.editForm.id = contactFieldType.id;
+ this.editForm.name = contactFieldType.name;
+ this.editForm.protocol = contactFieldType.protocol;
+ this.editForm.icon = contactFieldType.fontawesome_icon;
+
+ $('#modal-edit-contact-field-type').modal('show');
+ },
+ update: function update() {
+ this.persistClient('put', '/settings/personalization/contactfieldtypes/' + this.editForm.id, this.editForm, '#modal-edit-contact-field-type', this.edited);
+ },
+ showDelete: function showDelete(contactFieldType) {
+ this.editForm.id = contactFieldType.id;
+
+ $('#modal-delete-contact-field-type').modal('show');
+ },
+ trash: function trash() {
+ this.persistClient('delete', '/settings/personalization/contactfieldtypes/' + this.editForm.id, this.editForm, '#modal-delete-contact-field-type', this.deleted);
+ },
+ persistClient: function persistClient(method, uri, form, modal, success) {
+ var _this2 = this;
+
+ form.errors = {};
+
+ axios[method](uri, form).then(function (response) {
+ _this2.getContactFieldTypes();
+
+ form.id = '';
+ form.name = '';
+ form.protocol = '';
+ form.icon = '';
+ form.errors = [];
+
+ $(modal).modal('hide');
+
+ success = true;
+ }).catch(function (error) {
+ if (_typeof(error.response.data) === 'object') {
+ form.errors = _.flatten(_.toArray(error.response.data));
+ } else {
+ form.errors = ['Something went wrong. Please try again.'];
+ }
+ });
+ }
+ }
+});
+
+/***/ }),
+
/***/ "./node_modules/bootstrap/dist/js/umd/alert.js":
/***/ (function(module, exports, __webpack_require__) {
@@ -4602,6 +5434,21 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
});
+/***/ }),
+
+/***/ "./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-06458126\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/people/ContactInformation.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+exports = module.exports = __webpack_require__("./node_modules/css-loader/lib/css-base.js")(true);
+// imports
+
+
+// module
+exports.push([module.i, "\n", "", {"version":3,"sources":[],"names":[],"mappings":"","file":"ContactInformation.vue","sourceRoot":""}]);
+
+// exports
+
+
/***/ }),
/***/ "./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-2ff4435c\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/passport/PersonalAccessTokens.vue":
@@ -4617,6 +5464,36 @@ exports.push([module.i, "\n.m-b-none[data-v-2ff4435c] {\n margin-bottom: 0;\n
// exports
+/***/ }),
+
+/***/ "./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-4666559e\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/people/Addresses.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+exports = module.exports = __webpack_require__("./node_modules/css-loader/lib/css-base.js")(true);
+// imports
+
+
+// module
+exports.push([module.i, "\n", "", {"version":3,"sources":[],"names":[],"mappings":"","file":"Addresses.vue","sourceRoot":""}]);
+
+// exports
+
+
+/***/ }),
+
+/***/ "./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-553e50c2\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/settings/ContactFieldTypes.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+exports = module.exports = __webpack_require__("./node_modules/css-loader/lib/css-base.js")(true);
+// imports
+
+
+// module
+exports.push([module.i, "\n", "", {"version":3,"sources":[],"names":[],"mappings":"","file":"ContactFieldTypes.vue","sourceRoot":""}]);
+
+// exports
+
+
/***/ }),
/***/ "./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-e79f7702\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/passport/AuthorizedClients.vue":
@@ -32646,6 +33523,409 @@ module.exports = function normalizeComponent (
}
+/***/ }),
+
+/***/ "./node_modules/vue-loader/lib/template-compiler/index.js?{\"id\":\"data-v-06458126\",\"hasScoped\":true,\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0&bustCache!./resources/assets/js/components/people/ContactInformation.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+var render = function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c(
+ "div",
+ {
+ staticClass: "br2 pa3 mb3 f6",
+ class: [_vm.editMode ? "bg-washed-yellow b--yellow ba" : "bg-near-white"]
+ },
+ [
+ _c("div", { staticClass: "w-100 dt" }, [
+ _c("div", { staticClass: "dtc" }, [
+ _c("h3", { staticClass: "f6 ttu normal" }, [
+ _vm._v(_vm._s(_vm.trans("people.contact_info_title")))
+ ])
+ ]),
+ _vm._v(" "),
+ _vm.contactInformationData.length > 0
+ ? _c("div", { staticClass: "dtc tr" }, [
+ !_vm.editMode
+ ? _c(
+ "a",
+ {
+ staticClass: "pointer",
+ on: {
+ click: function($event) {
+ _vm.editMode = true
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.edit")))]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.editMode
+ ? _c(
+ "a",
+ {
+ staticClass: "pointer",
+ on: {
+ click: function($event) {
+ ;[(_vm.editMode = false), (_vm.addMode = false)]
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.done")))]
+ )
+ : _vm._e()
+ ])
+ : _vm._e()
+ ]),
+ _vm._v(" "),
+ _vm.contactInformationData.length == 0 && !_vm.addMode
+ ? _c("p", { staticClass: "mb0" }, [
+ _c("a", { staticClass: "pointer", on: { click: _vm.toggleAdd } }, [
+ _vm._v(_vm._s(_vm.trans("app.add")))
+ ])
+ ])
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.contactInformationData.length > 0
+ ? _c(
+ "ul",
+ [
+ _vm._l(_vm.contactInformationData, function(contactInformation) {
+ return _c("li", { staticClass: "mb2" }, [
+ _c(
+ "div",
+ {
+ directives: [
+ {
+ name: "show",
+ rawName: "v-show",
+ value: !contactInformation.edit,
+ expression: "!contactInformation.edit"
+ }
+ ],
+ staticClass: "w-100 dt"
+ },
+ [
+ _c("div", { staticClass: "dtc" }, [
+ contactInformation.fontawesome_icon
+ ? _c("i", {
+ staticClass: "pr2 f6 light-silver",
+ class: contactInformation.fontawesome_icon
+ })
+ : _vm._e(),
+ _vm._v(" "),
+ !contactInformation.fontawesome_icon
+ ? _c("i", {
+ staticClass: "pr2 fa fa-address-card-o f6 gray"
+ })
+ : _vm._e(),
+ _vm._v(" "),
+ contactInformation.protocol
+ ? _c(
+ "a",
+ {
+ attrs: {
+ href:
+ contactInformation.protocol +
+ contactInformation.data
+ }
+ },
+ [_vm._v(_vm._s(contactInformation.data))]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ !contactInformation.protocol
+ ? _c(
+ "a",
+ { attrs: { href: contactInformation.data } },
+ [_vm._v(_vm._s(contactInformation.data))]
+ )
+ : _vm._e()
+ ]),
+ _vm._v(" "),
+ _vm.editMode
+ ? _c("div", { staticClass: "dtc tr" }, [
+ _c("i", {
+ staticClass: "fa fa-pencil-square-o pointer pr2",
+ on: {
+ click: function($event) {
+ _vm.toggleEdit(contactInformation)
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("i", {
+ staticClass: "fa fa-trash-o pointer",
+ on: {
+ click: function($event) {
+ _vm.trash(contactInformation)
+ }
+ }
+ })
+ ])
+ : _vm._e()
+ ]
+ ),
+ _vm._v(" "),
+ _c(
+ "div",
+ {
+ directives: [
+ {
+ name: "show",
+ rawName: "v-show",
+ value: contactInformation.edit,
+ expression: "contactInformation.edit"
+ }
+ ],
+ staticClass: "w-100"
+ },
+ [
+ _c("form", { staticClass: "measure center" }, [
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_info_form_content")
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.data,
+ expression: "updateForm.data"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.data },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "data",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "lh-copy mt3" }, [
+ _c(
+ "a",
+ {
+ staticClass: "btn btn-primary",
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.update(contactInformation)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.save")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "a",
+ {
+ staticClass: "btn",
+ on: {
+ click: function($event) {
+ _vm.toggleEdit(contactInformation)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ )
+ ])
+ ])
+ ]
+ )
+ ])
+ }),
+ _vm._v(" "),
+ _vm.editMode && !_vm.addMode
+ ? _c("li", [
+ _c(
+ "a",
+ { staticClass: "pointer", on: { click: _vm.toggleAdd } },
+ [_vm._v(_vm._s(_vm.trans("app.add")))]
+ )
+ ])
+ : _vm._e()
+ ],
+ 2
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.addMode
+ ? _c("div", [
+ _c("form", { staticClass: "measure center" }, [
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_info_form_contact_type")
+ ) +
+ " "
+ ),
+ _c(
+ "a",
+ {
+ staticClass: "fr normal",
+ attrs: {
+ href: "/settings/personalization",
+ target: "_blank"
+ }
+ },
+ [
+ _vm._v(
+ _vm._s(
+ _vm.trans("people.contact_info_form_personalize")
+ )
+ )
+ ]
+ )
+ ]),
+ _vm._v(" "),
+ _c(
+ "select",
+ {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.contact_field_type_id,
+ expression: "createForm.contact_field_type_id"
+ }
+ ],
+ staticClass: "db w-100 h2",
+ on: {
+ change: function($event) {
+ var $$selectedVal = Array.prototype.filter
+ .call($event.target.options, function(o) {
+ return o.selected
+ })
+ .map(function(o) {
+ var val = "_value" in o ? o._value : o.value
+ return val
+ })
+ _vm.$set(
+ _vm.createForm,
+ "contact_field_type_id",
+ $event.target.multiple
+ ? $$selectedVal
+ : $$selectedVal[0]
+ )
+ }
+ }
+ },
+ _vm._l(_vm.contactFieldTypes, function(contactFieldType) {
+ return _c(
+ "option",
+ { domProps: { value: contactFieldType.id } },
+ [
+ _vm._v(
+ "\n " +
+ _vm._s(contactFieldType.name) +
+ "\n "
+ )
+ ]
+ )
+ })
+ )
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(_vm.trans("people.contact_info_form_content")) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.data,
+ expression: "createForm.data"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.data },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.createForm, "data", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "lh-copy mt3" }, [
+ _c(
+ "a",
+ {
+ staticClass: "btn btn-primary",
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.store($event)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.add")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "a",
+ {
+ staticClass: "btn",
+ on: {
+ click: function($event) {
+ _vm.addMode = false
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ )
+ ])
+ ])
+ ])
+ : _vm._e()
+ ]
+ )
+}
+var staticRenderFns = []
+render._withStripped = true
+module.exports = { render: render, staticRenderFns: staticRenderFns }
+if (false) {
+ module.hot.accept()
+ if (module.hot.data) {
+ require("vue-hot-reload-api") .rerender("data-v-06458126", module.exports)
+ }
+}
+
/***/ }),
/***/ "./node_modules/vue-loader/lib/template-compiler/index.js?{\"id\":\"data-v-2ff4435c\",\"hasScoped\":true,\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0&bustCache!./resources/assets/js/components/passport/PersonalAccessTokens.vue":
@@ -33020,6 +34300,1578 @@ if (false) {
/***/ }),
+/***/ "./node_modules/vue-loader/lib/template-compiler/index.js?{\"id\":\"data-v-4666559e\",\"hasScoped\":true,\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0&bustCache!./resources/assets/js/components/people/Addresses.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+var render = function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c(
+ "div",
+ {
+ staticClass: "br2 pa3 mb3 f6",
+ class: [_vm.editMode ? "bg-washed-yellow b--yellow ba" : "bg-near-white"]
+ },
+ [
+ _c("div", { staticClass: "w-100 dt" }, [
+ _c("div", { staticClass: "dtc" }, [
+ _c("h3", { staticClass: "f6 ttu normal" }, [
+ _vm._v(_vm._s(_vm.trans("people.contact_address_title")))
+ ])
+ ]),
+ _vm._v(" "),
+ _vm.contactAddresses.length > 0
+ ? _c("div", { staticClass: "dtc tr" }, [
+ !_vm.editMode
+ ? _c(
+ "a",
+ {
+ staticClass: "pointer",
+ on: {
+ click: function($event) {
+ _vm.editMode = true
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.edit")))]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.editMode
+ ? _c(
+ "a",
+ {
+ staticClass: "pointer",
+ on: {
+ click: function($event) {
+ ;[(_vm.editMode = false), (_vm.addMode = false)]
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.done")))]
+ )
+ : _vm._e()
+ ])
+ : _vm._e()
+ ]),
+ _vm._v(" "),
+ _vm.contactAddresses.length == 0 && !_vm.addMode
+ ? _c("p", { staticClass: "mb0" }, [
+ _c("a", { staticClass: "pointer", on: { click: _vm.toggleAdd } }, [
+ _vm._v(_vm._s(_vm.trans("app.add")))
+ ])
+ ])
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.contactAddresses.length > 0
+ ? _c(
+ "ul",
+ [
+ _vm._l(_vm.contactAddresses, function(contactAddress) {
+ return _c("li", { staticClass: "mb2" }, [
+ _c(
+ "div",
+ {
+ directives: [
+ {
+ name: "show",
+ rawName: "v-show",
+ value: !contactAddress.edit,
+ expression: "!contactAddress.edit"
+ }
+ ],
+ staticClass: "w-100 dt"
+ },
+ [
+ _c("div", { staticClass: "dtc" }, [
+ _c("i", {
+ staticClass: "f6 light-silver fa fa-globe pr2"
+ }),
+ _vm._v(" "),
+ !_vm.editMode
+ ? _c(
+ "a",
+ {
+ attrs: {
+ href: contactAddress.googleMapAddress,
+ target: "_blank"
+ }
+ },
+ [_vm._v(_vm._s(contactAddress.address))]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.editMode
+ ? _c("span", [_vm._v(_vm._s(contactAddress.address))])
+ : _vm._e(),
+ _vm._v(" "),
+ _c("span", { staticClass: "light-silver" }, [
+ _vm._v("(" + _vm._s(contactAddress.name) + ")")
+ ]),
+ _vm._v(" "),
+ _vm.editMode
+ ? _c("div", { staticClass: "fr" }, [
+ _c("i", {
+ staticClass:
+ "fa fa-pencil-square-o pointer pr2",
+ on: {
+ click: function($event) {
+ _vm.toggleEdit(contactAddress)
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("i", {
+ staticClass: "fa fa-trash-o pointer",
+ on: {
+ click: function($event) {
+ _vm.trash(contactAddress)
+ }
+ }
+ })
+ ])
+ : _vm._e()
+ ])
+ ]
+ ),
+ _vm._v(" "),
+ _c(
+ "div",
+ {
+ directives: [
+ {
+ name: "show",
+ rawName: "v-show",
+ value: contactAddress.edit,
+ expression: "contactAddress.edit"
+ }
+ ],
+ staticClass: "w-100"
+ },
+ [
+ _c("form", { staticClass: "measure center" }, [
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_address_form_name")
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.name,
+ expression: "updateForm.name"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.name },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "name",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "people.contact_address_form_street"
+ )
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.street,
+ expression: "updateForm.street"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.street },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "street",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_address_form_city")
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.city,
+ expression: "updateForm.city"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.city },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "city",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "people.contact_address_form_province"
+ )
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.province,
+ expression: "updateForm.province"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.province },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "province",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "people.contact_address_form_postal_code"
+ )
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.postal_code,
+ expression: "updateForm.postal_code"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.updateForm.postal_code },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.updateForm,
+ "postal_code",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "people.contact_address_form_country"
+ )
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c(
+ "select",
+ {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.updateForm.country_id,
+ expression: "updateForm.country_id"
+ }
+ ],
+ staticClass: "db w-100 h2",
+ on: {
+ change: function($event) {
+ var $$selectedVal = Array.prototype.filter
+ .call($event.target.options, function(o) {
+ return o.selected
+ })
+ .map(function(o) {
+ var val =
+ "_value" in o ? o._value : o.value
+ return val
+ })
+ _vm.$set(
+ _vm.updateForm,
+ "country_id",
+ $event.target.multiple
+ ? $$selectedVal
+ : $$selectedVal[0]
+ )
+ }
+ }
+ },
+ _vm._l(_vm.countries, function(country) {
+ return _c(
+ "option",
+ { domProps: { value: country.id } },
+ [
+ _vm._v(
+ "\n " +
+ _vm._s(country.country) +
+ "\n "
+ )
+ ]
+ )
+ })
+ )
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "lh-copy mt3" }, [
+ _c(
+ "a",
+ {
+ staticClass: "btn btn-primary",
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.update(contactAddress)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.add")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "a",
+ {
+ staticClass: "btn",
+ on: {
+ click: function($event) {
+ _vm.toggleEdit(contactAddress)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ )
+ ])
+ ])
+ ]
+ )
+ ])
+ }),
+ _vm._v(" "),
+ _vm.editMode && !_vm.addMode
+ ? _c("li", [
+ _c(
+ "a",
+ { staticClass: "pointer", on: { click: _vm.toggleAdd } },
+ [_vm._v(_vm._s(_vm.trans("app.add")))]
+ )
+ ])
+ : _vm._e()
+ ],
+ 2
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.addMode
+ ? _c("div", [
+ _c("form", { staticClass: "measure center" }, [
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(_vm.trans("people.contact_address_form_name")) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.name,
+ expression: "createForm.name"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.name },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.createForm, "name", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(_vm.trans("people.contact_address_form_street")) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.street,
+ expression: "createForm.street"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.street },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.createForm, "street", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(_vm.trans("people.contact_address_form_city")) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.city,
+ expression: "createForm.city"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.city },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.createForm, "city", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_address_form_province")
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.province,
+ expression: "createForm.province"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.province },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.createForm, "province", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("people.contact_address_form_postal_code")
+ ) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.postal_code,
+ expression: "createForm.postal_code"
+ }
+ ],
+ staticClass: "pa2 db w-100",
+ attrs: { type: "text" },
+ domProps: { value: _vm.createForm.postal_code },
+ on: {
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.createForm,
+ "postal_code",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "mt3" }, [
+ _c("label", { staticClass: "db fw6 lh-copy f6" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(_vm.trans("people.contact_address_form_country")) +
+ "\n "
+ )
+ ]),
+ _vm._v(" "),
+ _c(
+ "select",
+ {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.country_id,
+ expression: "createForm.country_id"
+ }
+ ],
+ staticClass: "db w-100 h2",
+ on: {
+ change: function($event) {
+ var $$selectedVal = Array.prototype.filter
+ .call($event.target.options, function(o) {
+ return o.selected
+ })
+ .map(function(o) {
+ var val = "_value" in o ? o._value : o.value
+ return val
+ })
+ _vm.$set(
+ _vm.createForm,
+ "country_id",
+ $event.target.multiple
+ ? $$selectedVal
+ : $$selectedVal[0]
+ )
+ }
+ }
+ },
+ [
+ _c("option", { attrs: { value: "0" } }),
+ _vm._v(" "),
+ _vm._l(_vm.countries, function(country) {
+ return _c("option", { domProps: { value: country.id } }, [
+ _vm._v(
+ "\n " +
+ _vm._s(country.country) +
+ "\n "
+ )
+ ])
+ })
+ ],
+ 2
+ )
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "lh-copy mt3" }, [
+ _c(
+ "a",
+ {
+ staticClass: "btn btn-primary",
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.store($event)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.add")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "a",
+ {
+ staticClass: "btn",
+ on: {
+ click: function($event) {
+ _vm.addMode = false
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ )
+ ])
+ ])
+ ])
+ : _vm._e()
+ ]
+ )
+}
+var staticRenderFns = []
+render._withStripped = true
+module.exports = { render: render, staticRenderFns: staticRenderFns }
+if (false) {
+ module.hot.accept()
+ if (module.hot.data) {
+ require("vue-hot-reload-api") .rerender("data-v-4666559e", module.exports)
+ }
+}
+
+/***/ }),
+
+/***/ "./node_modules/vue-loader/lib/template-compiler/index.js?{\"id\":\"data-v-553e50c2\",\"hasScoped\":true,\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0&bustCache!./resources/assets/js/components/settings/ContactFieldTypes.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+var render = function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c("div", [
+ _c("h3", { staticClass: "with-actions" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans("settings.personalization_contact_field_type_title")
+ ) +
+ "\n "
+ ),
+ _c("a", { staticClass: "btn fr nt2", on: { click: _vm.add } }, [
+ _vm._v(
+ _vm._s(_vm.trans("settings.personalization_contact_field_type_add"))
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("p", [
+ _vm._v(
+ _vm._s(
+ _vm.trans("settings.personalization_contact_field_type_description")
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _vm.submitted
+ ? _c(
+ "div",
+ { staticClass: "pa2 ba b--yellow mb3 mt3 br2 bg-washed-yellow" },
+ [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_add_success"
+ )
+ ) +
+ "\n "
+ )
+ ]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.edited
+ ? _c(
+ "div",
+ { staticClass: "pa2 ba b--yellow mb3 mt3 br2 bg-washed-yellow" },
+ [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_edit_success"
+ )
+ ) +
+ "\n "
+ )
+ ]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _vm.deleted
+ ? _c(
+ "div",
+ { staticClass: "pa2 ba b--yellow mb3 mt3 br2 bg-washed-yellow" },
+ [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_delete_success"
+ )
+ ) +
+ "\n "
+ )
+ ]
+ )
+ : _vm._e(),
+ _vm._v(" "),
+ _c(
+ "div",
+ { staticClass: "dt dt--fixed w-100 collapse br--top br--bottom" },
+ [
+ _c("div", { staticClass: "dt-row" }, [
+ _c("div", { staticClass: "dtc" }, [
+ _c("div", { staticClass: "pa2 b" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_table_name"
+ )
+ ) +
+ "\n "
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "dtc" }, [
+ _c("div", { staticClass: "pa2 b" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_table_protocol"
+ )
+ ) +
+ "\n "
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "dtc tr" }, [
+ _c("div", { staticClass: "pa2 b" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_table_actions"
+ )
+ ) +
+ "\n "
+ )
+ ])
+ ])
+ ]),
+ _vm._v(" "),
+ _vm._l(_vm.contactFieldTypes, function(contactFieldType) {
+ return _c("div", { staticClass: "dt-row bb b--light-gray" }, [
+ _c("div", { staticClass: "dtc" }, [
+ _c("div", { staticClass: "pa2" }, [
+ contactFieldType.fontawesome_icon
+ ? _c("i", {
+ staticClass: "pr2",
+ class: contactFieldType.fontawesome_icon
+ })
+ : _vm._e(),
+ _vm._v(" "),
+ !contactFieldType.fontawesome_icon
+ ? _c("i", { staticClass: "pr2 fa fa-address-card-o" })
+ : _vm._e(),
+ _vm._v(
+ "\n " + _vm._s(contactFieldType.name) + "\n "
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "dtc" }, [
+ _c("code", { staticClass: "f7" }, [
+ _vm._v(
+ "\n " +
+ _vm._s(contactFieldType.protocol) +
+ "\n "
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "dtc tr" }, [
+ _c("div", { staticClass: "pa2" }, [
+ _c("i", {
+ staticClass: "fa fa-pencil-square-o pointer pr2",
+ on: {
+ click: function($event) {
+ _vm.edit(contactFieldType)
+ }
+ }
+ }),
+ _vm._v(" "),
+ contactFieldType.delible
+ ? _c("i", {
+ staticClass: "fa fa-trash-o pointer",
+ on: {
+ click: function($event) {
+ _vm.showDelete(contactFieldType)
+ }
+ }
+ })
+ : _vm._e()
+ ])
+ ])
+ ])
+ })
+ ],
+ 2
+ ),
+ _vm._v(" "),
+ _c(
+ "div",
+ {
+ staticClass: "modal",
+ attrs: { id: "modal-create-contact-field-type", tabindex: "-1" }
+ },
+ [
+ _c("div", { staticClass: "modal-dialog" }, [
+ _c("div", { staticClass: "modal-content" }, [
+ _c("div", { staticClass: "modal-header" }, [
+ _c("h5", { staticClass: "modal-title" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_title"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _vm._m(0)
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-body" }, [
+ _vm.createForm.errors.length > 0
+ ? _c("div", { staticClass: "alert alert-danger" }, [
+ _c("p", [_vm._v(_vm._s(_vm.trans("app.error_title")))]),
+ _vm._v(" "),
+ _c("br"),
+ _vm._v(" "),
+ _c(
+ "ul",
+ _vm._l(_vm.createForm.errors, function(error) {
+ return _c("li", [
+ _vm._v(
+ "\n " +
+ _vm._s(error) +
+ "\n "
+ )
+ ])
+ })
+ )
+ ])
+ : _vm._e(),
+ _vm._v(" "),
+ _c(
+ "form",
+ {
+ staticClass: "form-horizontal",
+ attrs: { role: "form" },
+ on: {
+ submit: function($event) {
+ $event.preventDefault()
+ _vm.store($event)
+ }
+ }
+ },
+ [
+ _c("div", { staticClass: "form-group" }, [
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "name" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_name"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.name,
+ expression: "createForm.name"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "name",
+ id: "name",
+ required: ""
+ },
+ domProps: { value: _vm.createForm.name },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.store($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.createForm,
+ "name",
+ $event.target.value
+ )
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "protocol" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_protocol"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.protocol,
+ expression: "createForm.protocol"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "protocol",
+ id: "protocol",
+ placeholder: "mailto:"
+ },
+ domProps: { value: _vm.createForm.protocol },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.store($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.createForm,
+ "protocol",
+ $event.target.value
+ )
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("small", { staticClass: "form-text text-muted" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_protocol_help"
+ )
+ )
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "icon" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_icon"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.createForm.icon,
+ expression: "createForm.icon"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "icon",
+ id: "icon",
+ placeholder: "fa fa-address-book-o"
+ },
+ domProps: { value: _vm.createForm.icon },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.store($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.createForm,
+ "icon",
+ $event.target.value
+ )
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("small", { staticClass: "form-text text-muted" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_icon_help"
+ )
+ )
+ )
+ ])
+ ])
+ ])
+ ]
+ )
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-footer" }, [
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-secondary",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-primary",
+ attrs: { type: "button" },
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.store($event)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.save")))]
+ )
+ ])
+ ])
+ ])
+ ]
+ ),
+ _vm._v(" "),
+ _c(
+ "div",
+ {
+ staticClass: "modal",
+ attrs: { id: "modal-edit-contact-field-type", tabindex: "-1" }
+ },
+ [
+ _c("div", { staticClass: "modal-dialog" }, [
+ _c("div", { staticClass: "modal-content" }, [
+ _c("div", { staticClass: "modal-header" }, [
+ _c("h5", { staticClass: "modal-title" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_edit_title"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _vm._m(1)
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-body" }, [
+ _vm.editForm.errors.length > 0
+ ? _c("div", { staticClass: "alert alert-danger" }, [
+ _c("p", [_vm._v(_vm._s(_vm.trans("app.error_title")))]),
+ _vm._v(" "),
+ _c("br"),
+ _vm._v(" "),
+ _c(
+ "ul",
+ _vm._l(_vm.editForm.errors, function(error) {
+ return _c("li", [
+ _vm._v(
+ "\n " +
+ _vm._s(error[1]) +
+ "\n "
+ )
+ ])
+ })
+ )
+ ])
+ : _vm._e(),
+ _vm._v(" "),
+ _c(
+ "form",
+ {
+ staticClass: "form-horizontal",
+ attrs: { role: "form" },
+ on: {
+ submit: function($event) {
+ $event.preventDefault()
+ _vm.update($event)
+ }
+ }
+ },
+ [
+ _c("div", { staticClass: "form-group" }, [
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "name" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_name"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.editForm.name,
+ expression: "editForm.name"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "name",
+ id: "name",
+ required: ""
+ },
+ domProps: { value: _vm.editForm.name },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.update($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.editForm, "name", $event.target.value)
+ }
+ }
+ })
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "protocol" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_protocol"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.editForm.protocol,
+ expression: "editForm.protocol"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "protocol",
+ id: "protocol",
+ placeholder: "mailto:"
+ },
+ domProps: { value: _vm.editForm.protocol },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.update($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(
+ _vm.editForm,
+ "protocol",
+ $event.target.value
+ )
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("small", { staticClass: "form-text text-muted" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_protocol_help"
+ )
+ )
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "form-group" }, [
+ _c("label", { attrs: { for: "icon" } }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_icon"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _c("input", {
+ directives: [
+ {
+ name: "model",
+ rawName: "v-model",
+ value: _vm.editForm.icon,
+ expression: "editForm.icon"
+ }
+ ],
+ staticClass: "form-control",
+ attrs: {
+ type: "text",
+ name: "icon",
+ id: "icon",
+ placeholder: "fa fa-address-book-o"
+ },
+ domProps: { value: _vm.editForm.icon },
+ on: {
+ keyup: function($event) {
+ if (
+ !("button" in $event) &&
+ _vm._k($event.keyCode, "enter", 13, $event.key)
+ ) {
+ return null
+ }
+ _vm.update($event)
+ },
+ input: function($event) {
+ if ($event.target.composing) {
+ return
+ }
+ _vm.$set(_vm.editForm, "icon", $event.target.value)
+ }
+ }
+ }),
+ _vm._v(" "),
+ _c("small", { staticClass: "form-text text-muted" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_icon_help"
+ )
+ )
+ )
+ ])
+ ])
+ ])
+ ]
+ )
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-footer" }, [
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-secondary",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-primary",
+ attrs: { type: "button" },
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.update($event)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.edit")))]
+ )
+ ])
+ ])
+ ])
+ ]
+ ),
+ _vm._v(" "),
+ _c(
+ "div",
+ {
+ staticClass: "modal",
+ attrs: { id: "modal-delete-contact-field-type", tabindex: "-1" }
+ },
+ [
+ _c("div", { staticClass: "modal-dialog" }, [
+ _c("div", { staticClass: "modal-content" }, [
+ _c("div", { staticClass: "modal-header" }, [
+ _c("h5", { staticClass: "modal-title" }, [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_delete_title"
+ )
+ )
+ )
+ ]),
+ _vm._v(" "),
+ _vm._m(2)
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-body" }, [
+ _c("p", [
+ _vm._v(
+ _vm._s(
+ _vm.trans(
+ "settings.personalization_contact_field_type_modal_delete_description"
+ )
+ )
+ )
+ ])
+ ]),
+ _vm._v(" "),
+ _c("div", { staticClass: "modal-footer" }, [
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-secondary",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.cancel")))]
+ ),
+ _vm._v(" "),
+ _c(
+ "button",
+ {
+ staticClass: "btn btn-danger",
+ attrs: { type: "button" },
+ on: {
+ click: function($event) {
+ $event.preventDefault()
+ _vm.trash($event)
+ }
+ }
+ },
+ [_vm._v(_vm._s(_vm.trans("app.delete")))]
+ )
+ ])
+ ])
+ ])
+ ]
+ )
+ ])
+}
+var staticRenderFns = [
+ function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c(
+ "button",
+ {
+ staticClass: "close",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_c("span", { attrs: { "aria-hidden": "true" } }, [_vm._v("×")])]
+ )
+ },
+ function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c(
+ "button",
+ {
+ staticClass: "close",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_c("span", { attrs: { "aria-hidden": "true" } }, [_vm._v("×")])]
+ )
+ },
+ function() {
+ var _vm = this
+ var _h = _vm.$createElement
+ var _c = _vm._self._c || _h
+ return _c(
+ "button",
+ {
+ staticClass: "close",
+ attrs: { type: "button", "data-dismiss": "modal" }
+ },
+ [_c("span", { attrs: { "aria-hidden": "true" } }, [_vm._v("×")])]
+ )
+ }
+]
+render._withStripped = true
+module.exports = { render: render, staticRenderFns: staticRenderFns }
+if (false) {
+ module.hot.accept()
+ if (module.hot.data) {
+ require("vue-hot-reload-api") .rerender("data-v-553e50c2", module.exports)
+ }
+}
+
+/***/ }),
+
/***/ "./node_modules/vue-loader/lib/template-compiler/index.js?{\"id\":\"data-v-e79f7702\",\"hasScoped\":true,\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0&bustCache!./resources/assets/js/components/passport/AuthorizedClients.vue":
/***/ (function(module, exports, __webpack_require__) {
@@ -33675,6 +36527,1612 @@ if (false) {
/***/ }),
+/***/ "./node_modules/vue-resource/dist/vue-resource.es2015.js":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Url", function() { return Url; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Http", function() { return Http; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Resource", function() { return Resource; });
+/*!
+ * vue-resource v1.3.4
+ * https://github.com/pagekit/vue-resource
+ * Released under the MIT License.
+ */
+
+/**
+ * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis)
+ */
+
+var RESOLVED = 0;
+var REJECTED = 1;
+var PENDING = 2;
+
+function Promise$1(executor) {
+
+ this.state = PENDING;
+ this.value = undefined;
+ this.deferred = [];
+
+ var promise = this;
+
+ try {
+ executor(function (x) {
+ promise.resolve(x);
+ }, function (r) {
+ promise.reject(r);
+ });
+ } catch (e) {
+ promise.reject(e);
+ }
+}
+
+Promise$1.reject = function (r) {
+ return new Promise$1(function (resolve, reject) {
+ reject(r);
+ });
+};
+
+Promise$1.resolve = function (x) {
+ return new Promise$1(function (resolve, reject) {
+ resolve(x);
+ });
+};
+
+Promise$1.all = function all(iterable) {
+ return new Promise$1(function (resolve, reject) {
+ var count = 0, result = [];
+
+ if (iterable.length === 0) {
+ resolve(result);
+ }
+
+ function resolver(i) {
+ return function (x) {
+ result[i] = x;
+ count += 1;
+
+ if (count === iterable.length) {
+ resolve(result);
+ }
+ };
+ }
+
+ for (var i = 0; i < iterable.length; i += 1) {
+ Promise$1.resolve(iterable[i]).then(resolver(i), reject);
+ }
+ });
+};
+
+Promise$1.race = function race(iterable) {
+ return new Promise$1(function (resolve, reject) {
+ for (var i = 0; i < iterable.length; i += 1) {
+ Promise$1.resolve(iterable[i]).then(resolve, reject);
+ }
+ });
+};
+
+var p$1 = Promise$1.prototype;
+
+p$1.resolve = function resolve(x) {
+ var promise = this;
+
+ if (promise.state === PENDING) {
+ if (x === promise) {
+ throw new TypeError('Promise settled with itself.');
+ }
+
+ var called = false;
+
+ try {
+ var then = x && x['then'];
+
+ if (x !== null && typeof x === 'object' && typeof then === 'function') {
+ then.call(x, function (x) {
+ if (!called) {
+ promise.resolve(x);
+ }
+ called = true;
+
+ }, function (r) {
+ if (!called) {
+ promise.reject(r);
+ }
+ called = true;
+ });
+ return;
+ }
+ } catch (e) {
+ if (!called) {
+ promise.reject(e);
+ }
+ return;
+ }
+
+ promise.state = RESOLVED;
+ promise.value = x;
+ promise.notify();
+ }
+};
+
+p$1.reject = function reject(reason) {
+ var promise = this;
+
+ if (promise.state === PENDING) {
+ if (reason === promise) {
+ throw new TypeError('Promise settled with itself.');
+ }
+
+ promise.state = REJECTED;
+ promise.value = reason;
+ promise.notify();
+ }
+};
+
+p$1.notify = function notify() {
+ var promise = this;
+
+ nextTick(function () {
+ if (promise.state !== PENDING) {
+ while (promise.deferred.length) {
+ var deferred = promise.deferred.shift(),
+ onResolved = deferred[0],
+ onRejected = deferred[1],
+ resolve = deferred[2],
+ reject = deferred[3];
+
+ try {
+ if (promise.state === RESOLVED) {
+ if (typeof onResolved === 'function') {
+ resolve(onResolved.call(undefined, promise.value));
+ } else {
+ resolve(promise.value);
+ }
+ } else if (promise.state === REJECTED) {
+ if (typeof onRejected === 'function') {
+ resolve(onRejected.call(undefined, promise.value));
+ } else {
+ reject(promise.value);
+ }
+ }
+ } catch (e) {
+ reject(e);
+ }
+ }
+ }
+ });
+};
+
+p$1.then = function then(onResolved, onRejected) {
+ var promise = this;
+
+ return new Promise$1(function (resolve, reject) {
+ promise.deferred.push([onResolved, onRejected, resolve, reject]);
+ promise.notify();
+ });
+};
+
+p$1.catch = function (onRejected) {
+ return this.then(undefined, onRejected);
+};
+
+/**
+ * Promise adapter.
+ */
+
+if (typeof Promise === 'undefined') {
+ window.Promise = Promise$1;
+}
+
+function PromiseObj(executor, context) {
+
+ if (executor instanceof Promise) {
+ this.promise = executor;
+ } else {
+ this.promise = new Promise(executor.bind(context));
+ }
+
+ this.context = context;
+}
+
+PromiseObj.all = function (iterable, context) {
+ return new PromiseObj(Promise.all(iterable), context);
+};
+
+PromiseObj.resolve = function (value, context) {
+ return new PromiseObj(Promise.resolve(value), context);
+};
+
+PromiseObj.reject = function (reason, context) {
+ return new PromiseObj(Promise.reject(reason), context);
+};
+
+PromiseObj.race = function (iterable, context) {
+ return new PromiseObj(Promise.race(iterable), context);
+};
+
+var p = PromiseObj.prototype;
+
+p.bind = function (context) {
+ this.context = context;
+ return this;
+};
+
+p.then = function (fulfilled, rejected) {
+
+ if (fulfilled && fulfilled.bind && this.context) {
+ fulfilled = fulfilled.bind(this.context);
+ }
+
+ if (rejected && rejected.bind && this.context) {
+ rejected = rejected.bind(this.context);
+ }
+
+ return new PromiseObj(this.promise.then(fulfilled, rejected), this.context);
+};
+
+p.catch = function (rejected) {
+
+ if (rejected && rejected.bind && this.context) {
+ rejected = rejected.bind(this.context);
+ }
+
+ return new PromiseObj(this.promise.catch(rejected), this.context);
+};
+
+p.finally = function (callback) {
+
+ return this.then(function (value) {
+ callback.call(this);
+ return value;
+ }, function (reason) {
+ callback.call(this);
+ return Promise.reject(reason);
+ }
+ );
+};
+
+/**
+ * Utility functions.
+ */
+
+var ref = {};
+var hasOwnProperty = ref.hasOwnProperty;
+
+var ref$1 = [];
+var slice = ref$1.slice;
+var debug = false;
+var ntick;
+
+var inBrowser = typeof window !== 'undefined';
+
+var Util = function (ref) {
+ var config = ref.config;
+ var nextTick = ref.nextTick;
+
+ ntick = nextTick;
+ debug = config.debug || !config.silent;
+};
+
+function warn(msg) {
+ if (typeof console !== 'undefined' && debug) {
+ console.warn('[VueResource warn]: ' + msg);
+ }
+}
+
+function error(msg) {
+ if (typeof console !== 'undefined') {
+ console.error(msg);
+ }
+}
+
+function nextTick(cb, ctx) {
+ return ntick(cb, ctx);
+}
+
+function trim(str) {
+ return str ? str.replace(/^\s*|\s*$/g, '') : '';
+}
+
+function trimEnd(str, chars) {
+
+ if (str && chars === undefined) {
+ return str.replace(/\s+$/, '');
+ }
+
+ if (!str || !chars) {
+ return str;
+ }
+
+ return str.replace(new RegExp(("[" + chars + "]+$")), '');
+}
+
+function toLower(str) {
+ return str ? str.toLowerCase() : '';
+}
+
+function toUpper(str) {
+ return str ? str.toUpperCase() : '';
+}
+
+var isArray = Array.isArray;
+
+function isString(val) {
+ return typeof val === 'string';
+}
+
+
+
+function isFunction(val) {
+ return typeof val === 'function';
+}
+
+function isObject(obj) {
+ return obj !== null && typeof obj === 'object';
+}
+
+function isPlainObject(obj) {
+ return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype;
+}
+
+function isBlob(obj) {
+ return typeof Blob !== 'undefined' && obj instanceof Blob;
+}
+
+function isFormData(obj) {
+ return typeof FormData !== 'undefined' && obj instanceof FormData;
+}
+
+function when(value, fulfilled, rejected) {
+
+ var promise = PromiseObj.resolve(value);
+
+ if (arguments.length < 2) {
+ return promise;
+ }
+
+ return promise.then(fulfilled, rejected);
+}
+
+function options(fn, obj, opts) {
+
+ opts = opts || {};
+
+ if (isFunction(opts)) {
+ opts = opts.call(obj);
+ }
+
+ return merge(fn.bind({$vm: obj, $options: opts}), fn, {$options: opts});
+}
+
+function each(obj, iterator) {
+
+ var i, key;
+
+ if (isArray(obj)) {
+ for (i = 0; i < obj.length; i++) {
+ iterator.call(obj[i], obj[i], i);
+ }
+ } else if (isObject(obj)) {
+ for (key in obj) {
+ if (hasOwnProperty.call(obj, key)) {
+ iterator.call(obj[key], obj[key], key);
+ }
+ }
+ }
+
+ return obj;
+}
+
+var assign = Object.assign || _assign;
+
+function merge(target) {
+
+ var args = slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+ _merge(target, source, true);
+ });
+
+ return target;
+}
+
+function defaults(target) {
+
+ var args = slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+
+ for (var key in source) {
+ if (target[key] === undefined) {
+ target[key] = source[key];
+ }
+ }
+
+ });
+
+ return target;
+}
+
+function _assign(target) {
+
+ var args = slice.call(arguments, 1);
+
+ args.forEach(function (source) {
+ _merge(target, source);
+ });
+
+ return target;
+}
+
+function _merge(target, source, deep) {
+ for (var key in source) {
+ if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
+ if (isPlainObject(source[key]) && !isPlainObject(target[key])) {
+ target[key] = {};
+ }
+ if (isArray(source[key]) && !isArray(target[key])) {
+ target[key] = [];
+ }
+ _merge(target[key], source[key], deep);
+ } else if (source[key] !== undefined) {
+ target[key] = source[key];
+ }
+ }
+}
+
+/**
+ * Root Prefix Transform.
+ */
+
+var root = function (options$$1, next) {
+
+ var url = next(options$$1);
+
+ if (isString(options$$1.root) && !/^(https?:)?\//.test(url)) {
+ url = trimEnd(options$$1.root, '/') + '/' + url;
+ }
+
+ return url;
+};
+
+/**
+ * Query Parameter Transform.
+ */
+
+var query = function (options$$1, next) {
+
+ var urlParams = Object.keys(Url.options.params), query = {}, url = next(options$$1);
+
+ each(options$$1.params, function (value, key) {
+ if (urlParams.indexOf(key) === -1) {
+ query[key] = value;
+ }
+ });
+
+ query = Url.params(query);
+
+ if (query) {
+ url += (url.indexOf('?') == -1 ? '?' : '&') + query;
+ }
+
+ return url;
+};
+
+/**
+ * URL Template v2.0.6 (https://github.com/bramstein/url-template)
+ */
+
+function expand(url, params, variables) {
+
+ var tmpl = parse(url), expanded = tmpl.expand(params);
+
+ if (variables) {
+ variables.push.apply(variables, tmpl.vars);
+ }
+
+ return expanded;
+}
+
+function parse(template) {
+
+ var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = [];
+
+ return {
+ vars: variables,
+ expand: function expand(context) {
+ return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) {
+ if (expression) {
+
+ var operator = null, values = [];
+
+ if (operators.indexOf(expression.charAt(0)) !== -1) {
+ operator = expression.charAt(0);
+ expression = expression.substr(1);
+ }
+
+ expression.split(/,/g).forEach(function (variable) {
+ var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
+ values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
+ variables.push(tmp[1]);
+ });
+
+ if (operator && operator !== '+') {
+
+ var separator = ',';
+
+ if (operator === '?') {
+ separator = '&';
+ } else if (operator !== '#') {
+ separator = operator;
+ }
+
+ return (values.length !== 0 ? operator : '') + values.join(separator);
+ } else {
+ return values.join(',');
+ }
+
+ } else {
+ return encodeReserved(literal);
+ }
+ });
+ }
+ };
+}
+
+function getValues(context, operator, key, modifier) {
+
+ var value = context[key], result = [];
+
+ if (isDefined(value) && value !== '') {
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
+ value = value.toString();
+
+ if (modifier && modifier !== '*') {
+ value = value.substring(0, parseInt(modifier, 10));
+ }
+
+ result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
+ } else {
+ if (modifier === '*') {
+ if (Array.isArray(value)) {
+ value.filter(isDefined).forEach(function (value) {
+ result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null));
+ });
+ } else {
+ Object.keys(value).forEach(function (k) {
+ if (isDefined(value[k])) {
+ result.push(encodeValue(operator, value[k], k));
+ }
+ });
+ }
+ } else {
+ var tmp = [];
+
+ if (Array.isArray(value)) {
+ value.filter(isDefined).forEach(function (value) {
+ tmp.push(encodeValue(operator, value));
+ });
+ } else {
+ Object.keys(value).forEach(function (k) {
+ if (isDefined(value[k])) {
+ tmp.push(encodeURIComponent(k));
+ tmp.push(encodeValue(operator, value[k].toString()));
+ }
+ });
+ }
+
+ if (isKeyOperator(operator)) {
+ result.push(encodeURIComponent(key) + '=' + tmp.join(','));
+ } else if (tmp.length !== 0) {
+ result.push(tmp.join(','));
+ }
+ }
+ }
+ } else {
+ if (operator === ';') {
+ result.push(encodeURIComponent(key));
+ } else if (value === '' && (operator === '&' || operator === '?')) {
+ result.push(encodeURIComponent(key) + '=');
+ } else if (value === '') {
+ result.push('');
+ }
+ }
+
+ return result;
+}
+
+function isDefined(value) {
+ return value !== undefined && value !== null;
+}
+
+function isKeyOperator(operator) {
+ return operator === ';' || operator === '&' || operator === '?';
+}
+
+function encodeValue(operator, value, key) {
+
+ value = (operator === '+' || operator === '#') ? encodeReserved(value) : encodeURIComponent(value);
+
+ if (key) {
+ return encodeURIComponent(key) + '=' + value;
+ } else {
+ return value;
+ }
+}
+
+function encodeReserved(str) {
+ return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {
+ if (!/%[0-9A-Fa-f]/.test(part)) {
+ part = encodeURI(part);
+ }
+ return part;
+ }).join('');
+}
+
+/**
+ * URL Template (RFC 6570) Transform.
+ */
+
+var template = function (options) {
+
+ var variables = [], url = expand(options.url, options.params, variables);
+
+ variables.forEach(function (key) {
+ delete options.params[key];
+ });
+
+ return url;
+};
+
+/**
+ * Service for URL templating.
+ */
+
+function Url(url, params) {
+
+ var self = this || {}, options$$1 = url, transform;
+
+ if (isString(url)) {
+ options$$1 = {url: url, params: params};
+ }
+
+ options$$1 = merge({}, Url.options, self.$options, options$$1);
+
+ Url.transforms.forEach(function (handler) {
+
+ if (isString(handler)) {
+ handler = Url.transform[handler];
+ }
+
+ if (isFunction(handler)) {
+ transform = factory(handler, transform, self.$vm);
+ }
+
+ });
+
+ return transform(options$$1);
+}
+
+/**
+ * Url options.
+ */
+
+Url.options = {
+ url: '',
+ root: null,
+ params: {}
+};
+
+/**
+ * Url transforms.
+ */
+
+Url.transform = {template: template, query: query, root: root};
+Url.transforms = ['template', 'query', 'root'];
+
+/**
+ * Encodes a Url parameter string.
+ *
+ * @param {Object} obj
+ */
+
+Url.params = function (obj) {
+
+ var params = [], escape = encodeURIComponent;
+
+ params.add = function (key, value) {
+
+ if (isFunction(value)) {
+ value = value();
+ }
+
+ if (value === null) {
+ value = '';
+ }
+
+ this.push(escape(key) + '=' + escape(value));
+ };
+
+ serialize(params, obj);
+
+ return params.join('&').replace(/%20/g, '+');
+};
+
+/**
+ * Parse a URL and return its components.
+ *
+ * @param {String} url
+ */
+
+Url.parse = function (url) {
+
+ var el = document.createElement('a');
+
+ if (document.documentMode) {
+ el.href = url;
+ url = el.href;
+ }
+
+ el.href = url;
+
+ return {
+ href: el.href,
+ protocol: el.protocol ? el.protocol.replace(/:$/, '') : '',
+ port: el.port,
+ host: el.host,
+ hostname: el.hostname,
+ pathname: el.pathname.charAt(0) === '/' ? el.pathname : '/' + el.pathname,
+ search: el.search ? el.search.replace(/^\?/, '') : '',
+ hash: el.hash ? el.hash.replace(/^#/, '') : ''
+ };
+};
+
+function factory(handler, next, vm) {
+ return function (options$$1) {
+ return handler.call(vm, options$$1, next);
+ };
+}
+
+function serialize(params, obj, scope) {
+
+ var array = isArray(obj), plain = isPlainObject(obj), hash;
+
+ each(obj, function (value, key) {
+
+ hash = isObject(value) || isArray(value);
+
+ if (scope) {
+ key = scope + '[' + (plain || hash ? key : '') + ']';
+ }
+
+ if (!scope && array) {
+ params.add(value.name, value.value);
+ } else if (hash) {
+ serialize(params, value, key);
+ } else {
+ params.add(key, value);
+ }
+ });
+}
+
+/**
+ * XDomain client (Internet Explorer).
+ */
+
+var xdrClient = function (request) {
+ return new PromiseObj(function (resolve) {
+
+ var xdr = new XDomainRequest(), handler = function (ref) {
+ var type = ref.type;
+
+
+ var status = 0;
+
+ if (type === 'load') {
+ status = 200;
+ } else if (type === 'error') {
+ status = 500;
+ }
+
+ resolve(request.respondWith(xdr.responseText, {status: status}));
+ };
+
+ request.abort = function () { return xdr.abort(); };
+
+ xdr.open(request.method, request.getUrl());
+
+ if (request.timeout) {
+ xdr.timeout = request.timeout;
+ }
+
+ xdr.onload = handler;
+ xdr.onabort = handler;
+ xdr.onerror = handler;
+ xdr.ontimeout = handler;
+ xdr.onprogress = function () {};
+ xdr.send(request.getBody());
+ });
+};
+
+/**
+ * CORS Interceptor.
+ */
+
+var SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest();
+
+var cors = function (request, next) {
+
+ if (inBrowser) {
+
+ var orgUrl = Url.parse(location.href);
+ var reqUrl = Url.parse(request.getUrl());
+
+ if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) {
+
+ request.crossOrigin = true;
+ request.emulateHTTP = false;
+
+ if (!SUPPORTS_CORS) {
+ request.client = xdrClient;
+ }
+ }
+ }
+
+ next();
+};
+
+/**
+ * Form data Interceptor.
+ */
+
+var form = function (request, next) {
+
+ if (isFormData(request.body)) {
+
+ request.headers.delete('Content-Type');
+
+ } else if (isObject(request.body) && request.emulateJSON) {
+
+ request.body = Url.params(request.body);
+ request.headers.set('Content-Type', 'application/x-www-form-urlencoded');
+ }
+
+ next();
+};
+
+/**
+ * JSON Interceptor.
+ */
+
+var json = function (request, next) {
+
+ var type = request.headers.get('Content-Type') || '';
+
+ if (isObject(request.body) && type.indexOf('application/json') === 0) {
+ request.body = JSON.stringify(request.body);
+ }
+
+ next(function (response) {
+
+ return response.bodyText ? when(response.text(), function (text) {
+
+ type = response.headers.get('Content-Type') || '';
+
+ if (type.indexOf('application/json') === 0 || isJson(text)) {
+
+ try {
+ response.body = JSON.parse(text);
+ } catch (e) {
+ response.body = null;
+ }
+
+ } else {
+ response.body = text;
+ }
+
+ return response;
+
+ }) : response;
+
+ });
+};
+
+function isJson(str) {
+
+ var start = str.match(/^\[|^\{(?!\{)/), end = {'[': /]$/, '{': /}$/};
+
+ return start && end[start[0]].test(str);
+}
+
+/**
+ * JSONP client (Browser).
+ */
+
+var jsonpClient = function (request) {
+ return new PromiseObj(function (resolve) {
+
+ var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script;
+
+ handler = function (ref) {
+ var type = ref.type;
+
+
+ var status = 0;
+
+ if (type === 'load' && body !== null) {
+ status = 200;
+ } else if (type === 'error') {
+ status = 500;
+ }
+
+ if (status && window[callback]) {
+ delete window[callback];
+ document.body.removeChild(script);
+ }
+
+ resolve(request.respondWith(body, {status: status}));
+ };
+
+ window[callback] = function (result) {
+ body = JSON.stringify(result);
+ };
+
+ request.abort = function () {
+ handler({type: 'abort'});
+ };
+
+ request.params[name] = callback;
+
+ if (request.timeout) {
+ setTimeout(request.abort, request.timeout);
+ }
+
+ script = document.createElement('script');
+ script.src = request.getUrl();
+ script.type = 'text/javascript';
+ script.async = true;
+ script.onload = handler;
+ script.onerror = handler;
+
+ document.body.appendChild(script);
+ });
+};
+
+/**
+ * JSONP Interceptor.
+ */
+
+var jsonp = function (request, next) {
+
+ if (request.method == 'JSONP') {
+ request.client = jsonpClient;
+ }
+
+ next();
+};
+
+/**
+ * Before Interceptor.
+ */
+
+var before = function (request, next) {
+
+ if (isFunction(request.before)) {
+ request.before.call(this, request);
+ }
+
+ next();
+};
+
+/**
+ * HTTP method override Interceptor.
+ */
+
+var method = function (request, next) {
+
+ if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) {
+ request.headers.set('X-HTTP-Method-Override', request.method);
+ request.method = 'POST';
+ }
+
+ next();
+};
+
+/**
+ * Header Interceptor.
+ */
+
+var header = function (request, next) {
+
+ var headers = assign({}, Http.headers.common,
+ !request.crossOrigin ? Http.headers.custom : {},
+ Http.headers[toLower(request.method)]
+ );
+
+ each(headers, function (value, name) {
+ if (!request.headers.has(name)) {
+ request.headers.set(name, value);
+ }
+ });
+
+ next();
+};
+
+/**
+ * XMLHttp client (Browser).
+ */
+
+var xhrClient = function (request) {
+ return new PromiseObj(function (resolve) {
+
+ var xhr = new XMLHttpRequest(), handler = function (event) {
+
+ var response = request.respondWith(
+ 'response' in xhr ? xhr.response : xhr.responseText, {
+ status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug
+ statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText)
+ }
+ );
+
+ each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) {
+ response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1));
+ });
+
+ resolve(response);
+ };
+
+ request.abort = function () { return xhr.abort(); };
+
+ if (request.progress) {
+ if (request.method === 'GET') {
+ xhr.addEventListener('progress', request.progress);
+ } else if (/^(POST|PUT)$/i.test(request.method)) {
+ xhr.upload.addEventListener('progress', request.progress);
+ }
+ }
+
+ xhr.open(request.method, request.getUrl(), true);
+
+ if (request.timeout) {
+ xhr.timeout = request.timeout;
+ }
+
+ if (request.responseType && 'responseType' in xhr) {
+ xhr.responseType = request.responseType;
+ }
+
+ if (request.withCredentials || request.credentials) {
+ xhr.withCredentials = true;
+ }
+
+ if (!request.crossOrigin) {
+ request.headers.set('X-Requested-With', 'XMLHttpRequest');
+ }
+
+ request.headers.forEach(function (value, name) {
+ xhr.setRequestHeader(name, value);
+ });
+
+ xhr.onload = handler;
+ xhr.onabort = handler;
+ xhr.onerror = handler;
+ xhr.ontimeout = handler;
+ xhr.send(request.getBody());
+ });
+};
+
+/**
+ * Http client (Node).
+ */
+
+var nodeClient = function (request) {
+
+ var client = __webpack_require__(1);
+
+ return new PromiseObj(function (resolve) {
+
+ var url = request.getUrl();
+ var body = request.getBody();
+ var method = request.method;
+ var headers = {}, handler;
+
+ request.headers.forEach(function (value, name) {
+ headers[name] = value;
+ });
+
+ client(url, {body: body, method: method, headers: headers}).then(handler = function (resp) {
+
+ var response = request.respondWith(resp.body, {
+ status: resp.statusCode,
+ statusText: trim(resp.statusMessage)
+ }
+ );
+
+ each(resp.headers, function (value, name) {
+ response.headers.set(name, value);
+ });
+
+ resolve(response);
+
+ }, function (error$$1) { return handler(error$$1.response); });
+ });
+};
+
+/**
+ * Base client.
+ */
+
+var Client = function (context) {
+
+ var reqHandlers = [sendRequest], resHandlers = [], handler;
+
+ if (!isObject(context)) {
+ context = null;
+ }
+
+ function Client(request) {
+ return new PromiseObj(function (resolve, reject) {
+
+ function exec() {
+
+ handler = reqHandlers.pop();
+
+ if (isFunction(handler)) {
+ handler.call(context, request, next);
+ } else {
+ warn(("Invalid interceptor of type " + (typeof handler) + ", must be a function"));
+ next();
+ }
+ }
+
+ function next(response) {
+
+ if (isFunction(response)) {
+
+ resHandlers.unshift(response);
+
+ } else if (isObject(response)) {
+
+ resHandlers.forEach(function (handler) {
+ response = when(response, function (response) {
+ return handler.call(context, response) || response;
+ }, reject);
+ });
+
+ when(response, resolve, reject);
+
+ return;
+ }
+
+ exec();
+ }
+
+ exec();
+
+ }, context);
+ }
+
+ Client.use = function (handler) {
+ reqHandlers.push(handler);
+ };
+
+ return Client;
+};
+
+function sendRequest(request, resolve) {
+
+ var client = request.client || (inBrowser ? xhrClient : nodeClient);
+
+ resolve(client(request));
+}
+
+/**
+ * HTTP Headers.
+ */
+
+var Headers = function Headers(headers) {
+ var this$1 = this;
+
+
+ this.map = {};
+
+ each(headers, function (value, name) { return this$1.append(name, value); });
+};
+
+Headers.prototype.has = function has (name) {
+ return getName(this.map, name) !== null;
+};
+
+Headers.prototype.get = function get (name) {
+
+ var list = this.map[getName(this.map, name)];
+
+ return list ? list.join() : null;
+};
+
+Headers.prototype.getAll = function getAll (name) {
+ return this.map[getName(this.map, name)] || [];
+};
+
+Headers.prototype.set = function set (name, value) {
+ this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)];
+};
+
+Headers.prototype.append = function append (name, value){
+
+ var list = this.map[getName(this.map, name)];
+
+ if (list) {
+ list.push(trim(value));
+ } else {
+ this.set(name, value);
+ }
+};
+
+Headers.prototype.delete = function delete$1 (name){
+ delete this.map[getName(this.map, name)];
+};
+
+Headers.prototype.deleteAll = function deleteAll (){
+ this.map = {};
+};
+
+Headers.prototype.forEach = function forEach (callback, thisArg) {
+ var this$1 = this;
+
+ each(this.map, function (list, name) {
+ each(list, function (value) { return callback.call(thisArg, value, name, this$1); });
+ });
+};
+
+function getName(map, name) {
+ return Object.keys(map).reduce(function (prev, curr) {
+ return toLower(name) === toLower(curr) ? curr : prev;
+ }, null);
+}
+
+function normalizeName(name) {
+
+ if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
+ throw new TypeError('Invalid character in header field name');
+ }
+
+ return trim(name);
+}
+
+/**
+ * HTTP Response.
+ */
+
+var Response = function Response(body, ref) {
+ var url = ref.url;
+ var headers = ref.headers;
+ var status = ref.status;
+ var statusText = ref.statusText;
+
+
+ this.url = url;
+ this.ok = status >= 200 && status < 300;
+ this.status = status || 0;
+ this.statusText = statusText || '';
+ this.headers = new Headers(headers);
+ this.body = body;
+
+ if (isString(body)) {
+
+ this.bodyText = body;
+
+ } else if (isBlob(body)) {
+
+ this.bodyBlob = body;
+
+ if (isBlobText(body)) {
+ this.bodyText = blobText(body);
+ }
+ }
+};
+
+Response.prototype.blob = function blob () {
+ return when(this.bodyBlob);
+};
+
+Response.prototype.text = function text () {
+ return when(this.bodyText);
+};
+
+Response.prototype.json = function json () {
+ return when(this.text(), function (text) { return JSON.parse(text); });
+};
+
+Object.defineProperty(Response.prototype, 'data', {
+
+ get: function get() {
+ return this.body;
+ },
+
+ set: function set(body) {
+ this.body = body;
+ }
+
+});
+
+function blobText(body) {
+ return new PromiseObj(function (resolve) {
+
+ var reader = new FileReader();
+
+ reader.readAsText(body);
+ reader.onload = function () {
+ resolve(reader.result);
+ };
+
+ });
+}
+
+function isBlobText(body) {
+ return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1;
+}
+
+/**
+ * HTTP Request.
+ */
+
+var Request = function Request(options$$1) {
+
+ this.body = null;
+ this.params = {};
+
+ assign(this, options$$1, {
+ method: toUpper(options$$1.method || 'GET')
+ });
+
+ if (!(this.headers instanceof Headers)) {
+ this.headers = new Headers(this.headers);
+ }
+};
+
+Request.prototype.getUrl = function getUrl (){
+ return Url(this);
+};
+
+Request.prototype.getBody = function getBody (){
+ return this.body;
+};
+
+Request.prototype.respondWith = function respondWith (body, options$$1) {
+ return new Response(body, assign(options$$1 || {}, {url: this.getUrl()}));
+};
+
+/**
+ * Service for sending network requests.
+ */
+
+var COMMON_HEADERS = {'Accept': 'application/json, text/plain, */*'};
+var JSON_CONTENT_TYPE = {'Content-Type': 'application/json;charset=utf-8'};
+
+function Http(options$$1) {
+
+ var self = this || {}, client = Client(self.$vm);
+
+ defaults(options$$1 || {}, self.$options, Http.options);
+
+ Http.interceptors.forEach(function (handler) {
+
+ if (isString(handler)) {
+ handler = Http.interceptor[handler];
+ }
+
+ if (isFunction(handler)) {
+ client.use(handler);
+ }
+
+ });
+
+ return client(new Request(options$$1)).then(function (response) {
+
+ return response.ok ? response : PromiseObj.reject(response);
+
+ }, function (response) {
+
+ if (response instanceof Error) {
+ error(response);
+ }
+
+ return PromiseObj.reject(response);
+ });
+}
+
+Http.options = {};
+
+Http.headers = {
+ put: JSON_CONTENT_TYPE,
+ post: JSON_CONTENT_TYPE,
+ patch: JSON_CONTENT_TYPE,
+ delete: JSON_CONTENT_TYPE,
+ common: COMMON_HEADERS,
+ custom: {}
+};
+
+Http.interceptor = {before: before, method: method, jsonp: jsonp, json: json, form: form, header: header, cors: cors};
+Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors'];
+
+['get', 'delete', 'head', 'jsonp'].forEach(function (method$$1) {
+
+ Http[method$$1] = function (url, options$$1) {
+ return this(assign(options$$1 || {}, {url: url, method: method$$1}));
+ };
+
+});
+
+['post', 'put', 'patch'].forEach(function (method$$1) {
+
+ Http[method$$1] = function (url, body, options$$1) {
+ return this(assign(options$$1 || {}, {url: url, method: method$$1, body: body}));
+ };
+
+});
+
+/**
+ * Service for interacting with RESTful services.
+ */
+
+function Resource(url, params, actions, options$$1) {
+
+ var self = this || {}, resource = {};
+
+ actions = assign({},
+ Resource.actions,
+ actions
+ );
+
+ each(actions, function (action, name) {
+
+ action = merge({url: url, params: assign({}, params)}, options$$1, action);
+
+ resource[name] = function () {
+ return (self.$http || Http)(opts(action, arguments));
+ };
+ });
+
+ return resource;
+}
+
+function opts(action, args) {
+
+ var options$$1 = assign({}, action), params = {}, body;
+
+ switch (args.length) {
+
+ case 2:
+
+ params = args[0];
+ body = args[1];
+
+ break;
+
+ case 1:
+
+ if (/^(POST|PUT|PATCH)$/i.test(options$$1.method)) {
+ body = args[0];
+ } else {
+ params = args[0];
+ }
+
+ break;
+
+ case 0:
+
+ break;
+
+ default:
+
+ throw 'Expected up to 2 arguments [params, body], got ' + args.length + ' arguments';
+ }
+
+ options$$1.body = body;
+ options$$1.params = assign({}, options$$1.params, params);
+
+ return options$$1;
+}
+
+Resource.actions = {
+
+ get: {method: 'GET'},
+ save: {method: 'POST'},
+ query: {method: 'GET'},
+ update: {method: 'PUT'},
+ remove: {method: 'DELETE'},
+ delete: {method: 'DELETE'}
+
+};
+
+/**
+ * Install plugin.
+ */
+
+function plugin(Vue) {
+
+ if (plugin.installed) {
+ return;
+ }
+
+ Util(Vue);
+
+ Vue.url = Url;
+ Vue.http = Http;
+ Vue.resource = Resource;
+ Vue.Promise = PromiseObj;
+
+ Object.defineProperties(Vue.prototype, {
+
+ $url: {
+ get: function get() {
+ return options(Vue.url, this, this.$options.url);
+ }
+ },
+
+ $http: {
+ get: function get() {
+ return options(Vue.http, this, this.$options.http);
+ }
+ },
+
+ $resource: {
+ get: function get() {
+ return Vue.resource.bind(this);
+ }
+ },
+
+ $promise: {
+ get: function get() {
+ var this$1 = this;
+
+ return function (executor) { return new Vue.Promise(executor, this$1); };
+ }
+ }
+
+ });
+}
+
+if (typeof window !== 'undefined' && window.Vue) {
+ window.Vue.use(plugin);
+}
+
+/* harmony default export */ __webpack_exports__["default"] = (plugin);
+
+
+
+/***/ }),
+
+/***/ "./node_modules/vue-style-loader/index.js!./node_modules/css-loader/index.js?sourceMap!./node_modules/vue-loader/lib/style-compiler/index.js?{\"vue\":true,\"id\":\"data-v-06458126\",\"scoped\":true,\"hasInlineConfig\":true}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0&bustCache!./resources/assets/js/components/people/ContactInformation.vue":
+/***/ (function(module, exports, __webpack_require__) {
+
+// style-loader: Adds some css to the DOM by adding a
+
+
+ {{ trans('settings.personalization_contact_field_type_description') }}{{ trans('people.contact_address_title') }}
+
+
+
+
+
+
+ {{ trans('people.contact_info_title') }}
+
+
+
+
+ {{ trans('settings.personalization_contact_field_type_title') }}
+ {{ trans('settings.personalization_contact_field_type_add') }}
+
+
+ {{ contactFieldType.protocol }}
+
+