Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whatsapp Integration #1248

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
"Webkul\\UI\\": "packages/Webkul/UI/src",
"Webkul\\User\\": "packages/Webkul/User/src",
"Webkul\\WebForm\\": "packages/Webkul/WebForm/src",
"Webkul\\Workflow\\": "packages/Webkul/Workflow/src"
"Webkul\\Workflow\\": "packages/Webkul/Workflow/src",
"Webkul\\WhatsApp\\": "packages/Webkul/WhatsApp/src"
}
},
"autoload-dev": {
Expand Down
1 change: 1 addition & 0 deletions config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@
Webkul\User\Providers\UserServiceProvider::class,
Webkul\WebForm\Providers\WebFormServiceProvider::class,
Webkul\Workflow\Providers\WorkflowServiceProvider::class,
Webkul\WhatsApp\Providers\WhatsAppServiceProvider::class,
],

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public function run()
'name' => 'Direct',
'created_at' => $now,
'updated_at' => $now,
], [
'id' => 6,
'name' => 'WhatsApp',
'created_at' => $now,
'updated_at' => $now,
]
]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,15 @@ public function store()
{
$this->validate(request(), [
'type' => 'required',
'comment' => 'required_if:type,note',
'schedule_from' => 'required_unless:type,note',
'schedule_to' => 'required_unless:type,note',
'comment' => 'required_if:type,note,whatsapp',
'schedule_from' => 'required_unless:type,note,whatsapp',
'schedule_to' => 'required_unless:type,note,whatsapp',
]);

Event::dispatch('activity.create.before');

$activity = $this->activityRepository->create(array_merge(request()->all(), [
'is_done' => request('type') == 'note' ? 1 : 0,
'is_done' => request('type') == 'note' || request('type') == 'whatsapp' ? 1 : 0,
'user_id' => auth()->guard('user')->user()->id,
]));

Expand Down
5 changes: 3 additions & 2 deletions packages/Webkul/Admin/src/Resources/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import './bootstrap';
import hi_IN from 'vee-validate/dist/locale/hi';
import zh_CN from 'vee-validate/dist/locale/zh_CN';

import 'vue-cal/dist/i18n/ar.js';
import 'vue-cal/dist/i18n/tr.js';
import 'vue-cal/dist/i18n/en.es.js';
import 'vue-cal/dist/i18n/ar.es.js';
import 'vue-cal/dist/i18n/tr.es.js';


window.moment = require('moment');
Expand Down
44 changes: 44 additions & 0 deletions packages/Webkul/Admin/src/Resources/assets/sass/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1290,6 +1290,13 @@ body {
top: 8px;
}

&.whatsapp {
background-image: url("../images/note-icon.svg");
width: 16px;
height: 20px;
top: 8px;
}

&.call {
background-image: url("../images/call-icon.svg");
top: 9px;
Expand Down Expand Up @@ -2517,3 +2524,40 @@ body {
font-size: $font-size-md;
}
}

.image-container {
display: flex;
gap: 15px;
flex-wrap: wrap;

.image-preview-brick {
display: flex;
flex-direction: column;
width: 100px;

.image-preview {
height: 100px;
width: 100px;
border: 1px solid #c1c2c3;
position: relative;

img {
width: 100px;
height: 100px;
object-fit: contain;
cursor: pointer;
}

.image-preview-delete {
position: absolute;
bottom: 0;
right: 0;
cursor: pointer;
}
}

textarea {
height: auto;
}
}
}
11 changes: 11 additions & 0 deletions packages/Webkul/Admin/src/Resources/lang/en/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,12 @@
'meeting' => 'Meeting',
'lunch' => 'Lunch',
'file' => 'File',
'whatsapp-type-text' => 'Text',
'whatsapp-type-image' => 'Image',
'whatsapp-type-document' => 'Document',
'quote' => 'Quote',
'whatsapp' => 'WhatsApp',
'whatsapp-comment' => 'Message',
'create-quote' => 'Create Quote',
'type' => 'Type',
'description' => 'Description',
Expand Down Expand Up @@ -221,10 +226,15 @@
'meeting-scheduled' => 'Meeting scheduled at :from - :to',
'lunch-scheduled' => 'Lunch scheduled at :from - :to',
'file-added' => 'File added',
'whatsapp-added' => 'WhatsApp message added',
'quote-destroy-success' => 'Quote removed successfully.',
'tag-create-success' => 'Tag added successfully.',
'tag-destroy-success' => 'Tag removed successfully.',
'edit' => 'Edit',
'whatsapp-image-info' => 'Upload image(s)',
'whatsapp-image-format' => 'in PNG, JPG or WebP Format',
'whatsapp-image-error' => 'Only images (.jpeg, .jpg, .png, .webp, ..) are allowed.',
'whatsapp-caption' => 'Caption'
],

'quotes' => [
Expand Down Expand Up @@ -337,6 +347,7 @@
'back' => 'Back',
'type' => 'Type',
'note' => 'Note',
'whatsapp' => 'Whatsapp message',
'call' => 'Call',
'meeting' => 'Meeting',
'lunch' => 'Lunch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,115 @@ class="control"
@endif

{!! view_render_event('admin.leads.view.informations.activity_actions.quote.after', ['lead' => $lead]) !!}

{!! view_render_event('admin.leads.view.informations.activity_actions.whatsapp.before', ['lead' => $lead]) !!}

<tab name="{{ __('admin::app.leads.whatsapp') }}">
<form
action="{{ route('admin.activities.store') }}"
method="post"
data-vv-scope="whatsapp-form"
@submit.prevent="onSubmit($event, 'whatsapp-form')"
>

<input type="hidden" name="type" value="whatsapp">

<input type="hidden" name="lead_id" value="{{ $lead->id }}">

@csrf()

<div class="form-group" :class="[errors.has('whatsapp-form.type') ? 'has-error' : '']">
<label for="type" class="required">{{ __('admin::app.leads.type') }}</label>

<select
name="type"
class="control"
v-model="type"
v-validate="'required'"
data-vv-as="&quot;{{ __('admin::app.leads.type') }}&quot;"
>
<option value="" disabled selected>{{ __('admin::app.leads.select-type') }}</option>
<option value="text">{{ __('admin::app.leads.whatsapp-type-text') }}</option>
<option value="image">{{ __('admin::app.leads.whatsapp-type-image') }}</option>
<option value="document">{{ __('admin::app.leads.whatsapp-type-document') }}</option>
</select>

<span class="control-error" v-if="errors.has('whatsapp-form.type')">
@{{ errors.first('whatsapp-form.type') }}
</span>
</div>

<div
class="form-group"
v-if="type == 'text'"
:class="[errors.has('whatsapp-form.comment') ? 'has-error' : '']"
>
<label for="comment" class="required">{{ __('admin::app.leads.whatsapp-comment') }}</label>

<textarea
name="comment"
class="control"
id="whatsapp-comment"
v-validate="'required'"
data-vv-as="&quot;{{ __('admin::app.leads.whatsapp-comment') }}&quot;"
>{{ old('comment') }}</textarea>

<span class="control-error" v-if="errors.has('whatsapp-form.comment')">
@{{ errors.first('whatsapp-form.comment') }}
</span>
</div>

<upload-profile-image v-if="type == 'image'"></upload-profile-image>

<div
class="form-group"
v-if="type == 'document'"
:class="[errors.has('whatsapp-form.file') ? 'has-error' : '']"
>
<label for="file" class="required">{{ __('admin::app.leads.file') }}</label>

<input
type="file"
name="file"
class="control"
id="file"
v-validate="'required'"
data-vv-as="&quot;{{ __('admin::app.leads.file') }}&quot;"
>

<span class="control-error" v-if="errors.has('whatsapp-form.file')">
@{{ errors.first('whatsapp-form.file') }}
</span>
</div>

<div
class="form-group"
v-if="type == 'image' || type=='document'"
:class="[errors.has('whatsapp-form.caption') ? 'has-error' : '']"
>
<label for="caption">{{ __('admin::app.leads.whatsapp-caption') }}</label>

<input
type="text"
name="caption"
class="control"
id="caption"
data-vv-as="&quot;{{ __('admin::app.leads.whatsapp-caption') }}&quot;"
/>

<span class="control-error" v-if="errors.has('whatsapp-form.caption')">
@{{ errors.first('whatsapp-form.caption') }}
</span>
</div>

<button type="submit" class="btn btn-md btn-primary">
{{ __('admin::app.leads.send') }}
</button>

</form>
</tab>

{!! view_render_event('admin.leads.view.informations.activity_actions.whatsapp.after', ['lead' => $lead]) !!}
</tabs>
</script>

Expand Down Expand Up @@ -445,6 +554,8 @@ class="control"

'persons': []
},

type: '',
}
},

Expand Down Expand Up @@ -561,4 +672,98 @@ class="control"
});
</script>

<script type="text/x-template" id="upload-profile-image-template">
<div class="form-group">
<div class="image-container">
<div class="image-preview-brick" v-for="(image, index) in imageData">
<div class="image-preview">
<img v-if="imageData.length > 0" :src="image" @click="openImage(index)" />

<i class="image-preview-delete icon trash-icon" @click="deleteImage(index)"></i>
</div>

<div class="form-group">
<input
name="caption"
class="control"
/>
</div>
</div>

<div>
<div class="image-upload-brick">
<input
type="file"
name="image"
id="upload-profile"
ref="imageInput"
v-validate="'ext:jpeg,jpg,png,webp'"
accept="image/*"
multiple
@change="addImageView($event)"
>

<i class="icon upload-icon"></i>
</div>

<div class="image-info-brick">
<span class="field-info">
{{ __('admin::app.leads.whatsapp-image-info') }} <br>
{{ __('admin::app.leads.whatsapp-image-format') }}
</span>
</div>
</div>
</div>
</div>
</script>

<script>
Vue.component('upload-profile-image', {
template: '#upload-profile-image-template',

data: function() {
return {
imageData: [],
}
},

methods: {
addImageView () {
var imageInput = this.$refs.imageInput;

if (imageInput.files) {
imageInput.files.forEach((file) => {
if (file.type.includes('image/')) {
var reader = new FileReader();

reader.onload = (e) => {
console.log(e.target.result);
this.imageData.push(e.target.result);
}

reader.readAsDataURL(file);
} else {
imageInput.value = '';

alert('{{ __('admin::app.user.account.image_upload_message') }}');
}
});
}

console.log(this.imageData);
},

openImage (index) {
const win = window.open();
win.document.write(`<img src="${this.imageData[index]}">`);
win.document.close();
},

deleteImage (index) {
this.imageData.splice(index, 1);
}
}
});
</script>

@endpush
Loading
Loading