Browse Source

feat: refactor frontend code (#120)

* feat: take out all message and send audio

* feat: refactor send location

* feat: rename embed file

* feat: take out send contact, file and video

* feat: refactor send image

* fix: remove unused code

* feat: refactor send message

* feat: refactor user info

* refactor: account avatar & group

* feat: refactor account privacy

* feat: refactor app login

* feat: refactor UI & update package
pull/123/head v4.11.0
Aldino Kemal 2 years ago
committed by GitHub
parent
commit
3507cc90e8
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 11
      src/cmd/root.go
  2. 2
      src/go.mod
  3. 2
      src/go.sum
  4. 6
      src/main.go
  5. 111
      src/views/components/AccountAvatar.js
  6. 114
      src/views/components/AccountGroup.js
  7. 57
      src/views/components/AccountPrivacy.js
  8. 112
      src/views/components/AccountUserInfo.js
  9. 72
      src/views/components/AppLogin.js
  10. 38
      src/views/components/AppLogout.js
  11. 37
      src/views/components/AppReconnect.js
  12. 111
      src/views/components/MessageReact.js
  13. 103
      src/views/components/MessageRevoke.js
  14. 83
      src/views/components/MessageUpdate.js
  15. 107
      src/views/components/SendAudio.js
  16. 117
      src/views/components/SendContact.js
  17. 122
      src/views/components/SendFile.js
  18. 139
      src/views/components/SendImage.js
  19. 115
      src/views/components/SendLocation.js
  20. 118
      src/views/components/SendMessage.js
  21. 93
      src/views/components/SendPoll.js
  22. 145
      src/views/components/SendVideo.js
  23. 1689
      src/views/index.html

11
src/cmd/root.go

@ -27,8 +27,8 @@ import (
)
var (
EmbedIndex embed.FS
EmbedViews embed.FS
EmbedViewsComponent embed.FS
)
// rootCmd represents the base command when called without any subcommands
@ -61,17 +61,16 @@ func runRest(_ *cobra.Command, _ []string) {
log.Fatalln(err)
}
engine := html.NewFileSystem(http.FS(EmbedViews), ".html")
engine := html.NewFileSystem(http.FS(EmbedIndex), ".html")
engine.AddFunc("isEnableBasicAuth", func(token any) bool {
return token != nil
})
app := fiber.New(fiber.Config{
Views: engine,
BodyLimit: 50 * 1024 * 1024,
})
app.Static("/statics", "./statics")
app.Use("/components", filesystem.New(filesystem.Config{
Root: http.FS(EmbedViewsComponent),
Root: http.FS(EmbedViews),
PathPrefix: "views/components",
Browse: true,
}))
@ -141,9 +140,9 @@ func runRest(_ *cobra.Command, _ []string) {
}
// Execute adds all child commands to the root command and sets flags appropriately.
func Execute(embedViews embed.FS, embedViewsComponent embed.FS) {
func Execute(embedIndex embed.FS, embedViews embed.FS) {
EmbedIndex = embedIndex
EmbedViews = embedViews
EmbedViewsComponent = embedViewsComponent
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}

2
src/go.mod

@ -18,7 +18,7 @@ require (
github.com/stretchr/testify v1.9.0
github.com/valyala/fasthttp v1.52.0
go.mau.fi/libsignal v0.1.0
go.mau.fi/whatsmeow v0.0.0-20240308162537-79d9175fa09b
go.mau.fi/whatsmeow v0.0.0-20240312193055-9b989e1cc696
google.golang.org/protobuf v1.33.0
)

2
src/go.sum

@ -96,6 +96,8 @@ go.mau.fi/util v0.4.0 h1:S2X3qU4pUcb/vxBRfAuZjbrR9xVMAXSjQojNBLPBbhs=
go.mau.fi/util v0.4.0/go.mod h1:leeiHtgVBuN+W9aDii3deAXnfC563iN3WK6BF8/AjNw=
go.mau.fi/whatsmeow v0.0.0-20240308162537-79d9175fa09b h1:Jk0/Lu6LdLD4kh0L9Q+06n7EefcS8ZDAKpwGeX7C4YQ=
go.mau.fi/whatsmeow v0.0.0-20240308162537-79d9175fa09b/go.mod h1:lQHbhaG/fI+6hfGqz5Vzn2OBJBEZ05H0kCP6iJXriN4=
go.mau.fi/whatsmeow v0.0.0-20240312193055-9b989e1cc696 h1:F9ytx1yzfoclCS4DoEqQb1M0E5XpcX2j5dX8bIZjGFE=
go.mau.fi/whatsmeow v0.0.0-20240312193055-9b989e1cc696/go.mod h1:lQHbhaG/fI+6hfGqz5Vzn2OBJBEZ05H0kCP6iJXriN4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=

6
src/main.go

@ -6,11 +6,11 @@ import (
)
//go:embed views/index.html
var embedViews embed.FS
var embedIndex embed.FS
//go:embed views
var embedViewsComponent embed.FS
var embedViews embed.FS
func main() {
cmd.Execute(embedViews, embedViewsComponent)
cmd.Execute(embedIndex, embedViews)
}

111
src/views/components/AccountAvatar.js

@ -0,0 +1,111 @@
export default {
name: 'AccountAvatar',
data() {
return {
type: 'user',
phone: '',
image: null,
loading: false,
is_preview: false,
is_community: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
async openModal() {
this.handleReset();
$('#modalUserAvatar').modal('show');
},
async handleSubmit() {
try {
await this.submitApi();
showSuccessInfo("Avatar fetched")
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let response = await window.http.get(`/user/avatar?phone=${this.phone_id}&is_preview=${this.is_preview}&is_community=${this.is_community}`)
this.image = response.data.results.url;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.image = null;
this.type = 'user';
}
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer;">
<div class="content">
<div class="header">Avatar</div>
<div class="description">
You can search someone avatar by phone
</div>
</div>
</div>
<!-- Modal UserAvatar -->
<div class="ui small modal" id="modalUserAvatar">
<i class="close icon"></i>
<div class="header">
Search User Avatar
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Preview</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="compress" v-model="is_preview">
<label>Check for small size image</label>
</div>
</div>
<div class="field">
<label>Community</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="compress" v-model="is_community">
<label>Check is it's community image</label>
</div>
</div>
<button type="button" class="ui primary button" :class="{'loading': loading}"
@click="handleSubmit">
Search
</button>
</form>
<div v-if="image != null" class="center">
<img :src="image" alt="profile picture" style="padding-top: 10px; max-height: 200px">
</div>
</div>
</div>
`
}

114
src/views/components/AccountGroup.js

@ -0,0 +1,114 @@
export default {
name: 'AccountGroup',
data() {
return {
groups: []
}
},
methods: {
async openModal() {
try {
this.dtClear()
await this.submitApi();
$('#modalUserGroup').modal('show');
this.dtRebuild()
showSuccessInfo("Groups fetched")
} catch (err) {
showErrorInfo(err)
}
},
dtClear() {
$('#account_groups_table').DataTable().destroy();
},
dtRebuild() {
$('#account_groups_table').DataTable({
"pageLength": 100,
"reloadData": true,
}).draw();
},
async handleLeaveGroup(group_id) {
try {
const ok = confirm("Are you sure to leave this group?");
if (!ok) return;
await this.leaveGroupApi(group_id);
this.dtClear()
await this.submitApi();
this.dtRebuild()
showSuccessInfo("Group left")
} catch (err) {
showErrorInfo(err)
}
},
async leaveGroupApi(group_id) {
try {
let payload = new FormData();
payload.append("group_id", group_id)
await window.http.post(`/group/leave`, payload)
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
}
},
async submitApi() {
try {
let response = await window.http.get(`/user/my/groups`)
this.groups = response.data.results.data;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
}
},
formatDate: function (value) {
if (!value) return ''
return moment(value).format('LLL');
}
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer">
<div class="content">
<div class="header">My List Groups</div>
<div class="description">
Display all groups you joined
</div>
</div>
</div>
<!-- Modal AccountGroup -->
<div class="ui small modal" id="modalUserGroup">
<i class="close icon"></i>
<div class="header">
My Group List
</div>
<div class="content">
<table class="ui celled table" id="account_groups_table">
<thead>
<tr>
<th>Group ID</th>
<th>Name</th>
<th>Participants</th>
<th>Created At</th>
<th>Action</th>
</tr>
</thead>
<tbody v-if="groups != null">
<tr v-for="g in groups">
<td>{{ g.JID.split('@')[0] }}</td>
<td>{{ g.Name }}</td>
<td>{{ g.Participants.length }}</td>
<td>{{ formatDate(g.GroupCreated) }}</td>
<td>
<button class="ui red tiny button" @click="handleLeaveGroup(g.JID)">Leave</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
`
}

57
src/views/components/AccountPrivacy.js

@ -0,0 +1,57 @@
export default {
name: 'AccountPrivacy',
data() {
return {
data_privacy: null
}
},
methods: {
async openModal() {
try {
await this.submitApi();
$('#modalUserPrivacy').modal('show');
showSuccessInfo("Privacy fetched")
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
try {
let response = await window.http.get(`/user/my/privacy`)
this.data_privacy = response.data.results;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
}
},
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer">
<div class="content">
<div class="header">My Privacy Setting</div>
<div class="description">
Get your privacy settings
</div>
</div>
</div>
<!-- Modal UserPrivacy -->
<div class="ui small modal" id="modalUserPrivacy">
<i class="close icon"></i>
<div class="header">
My Privacy
</div>
<div class="content">
<ol v-if="data_privacy != null">
<li>Who can add Group : <b>{{ data_privacy.group_add }}</b></li>
<li>Who can see my Last Seen : <b>{{ data_privacy.last_seen }}</b></li>
<li>Who can see my Status : <b>{{ data_privacy.status }}</b></li>
<li>Who can see my Profile : <b>{{ data_privacy.profile }}</b></li>
<li>Read Receipts : <b>{{ data_privacy.read_receipts }}</b></li>
</ol>
</div>
</div>
`
}

112
src/views/components/AccountUserInfo.js

@ -0,0 +1,112 @@
export default {
name: 'AccountUserInfo',
data() {
return {
type: 'user',
phone: '',
//
name: null,
status: null,
devices: [],
//
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
async openModal() {
this.handleReset();
$('#modalUserInfo').modal('show');
},
async handleSubmit() {
try {
await this.submitApi();
showSuccessInfo("Info fetched")
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let response = await window.http.get(`/user/info?phone=${this.phone_id}`)
this.name = response.data.results.verified_name;
this.status = response.data.results.status;
this.devices = response.data.results.devices;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.name = null;
this.status = null;
this.devices = [];
this.type = 'user';
}
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer;">
<div class="content">
<div class="header">User Info</div>
<div class="description">
You can search someone user info by phone
</div>
</div>
</div>
<!-- Modal UserInfo -->
<div class="ui small modal" id="modalUserInfo">
<i class="close icon"></i>
<div class="header">
Search User Information
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<button type="button" class="ui primary button" :class="{'loading': loading}"
@click="handleSubmit">
Search
</button>
</form>
<div v-if="devices.length > 0" class="center">
<ol>
<li>Nama: {{ name }}</li>
<li>Status: {{ status }}</li>
<li>Device:
<ul>
<li v-for="d in devices">
{{ d.Device }}
</li>
</ul>
</li>
</ol>
</div>
</div>
</div>
`
}

72
src/views/components/AppLogin.js

@ -0,0 +1,72 @@
export default {
name: 'AppLogin',
data() {
return {
login_link: '',
login_duration_sec: 0,
}
},
methods: {
async openModal() {
try {
await this.submitApi();
$('#modalLogin').modal({
onApprove: function () {
return false;
}
}).modal('show');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
try {
let response = await window.http.get(`/app/login`)
let results = response.data.results;
this.login_link = results.qr_link;
this.login_duration_sec = results.qr_duration;
} catch (error) {
if (error.response) {
throw Error(error.response.data.message)
}
throw Error(error.message)
}
}
},
template: `
<div class="green card" @click="openModal" style="cursor: pointer">
<div class="content">
<div class="header">Login</div>
<div class="description">
Scan your QRCode and you can use all this API feature
</div>
</div>
</div>
<!-- Modal Login -->
<div class="ui small modal" id="modalLogin">
<i class="close icon"></i>
<div class="header">
Login Whatsapp
</div>
<div class="image content">
<div class="ui medium image">
<img :src="login_link" alt="qrCodeLogin">
</div>
<div class="description">
<div class="ui header">Please scan to connect</div>
<p>Open Setting > Linked Devices > Link Device</p>
<div style="padding-top: 50px;">
<i>Refresh QR Code in {{ login_duration_sec }} seconds to avoid link expiration</i>
</div>
</div>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" @click="submitApi">
Refresh QR Code
<i class="refresh icon"></i>
</div>
</div>
</div>
`
}

38
src/views/components/AppLogout.js

@ -0,0 +1,38 @@
export default {
name: 'AppLogout',
methods: {
async handleSubmit() {
try {
await this.submitApi()
showSuccessInfo("Logout success")
// fetch devices
this.$emit('reload-devices')
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
try {
await http.get(`/app/logout`)
} catch (error) {
if (error.response) {
throw Error(error.response.data.message)
}
throw Error(error.message)
}
}
},
template: `
<div class="green card" @click="handleSubmit" style="cursor: pointer">
<div class="content">
<div class="header">Logout</div>
<div class="description">
Remove your login session in application
</div>
</div>
</div>
`
}

37
src/views/components/AppReconnect.js

@ -0,0 +1,37 @@
export default {
name: 'AppReconnect',
methods: {
async handleSubmit() {
try {
await this.submitApi()
showSuccessInfo("Reconnect success")
// fetch devices
this.$emit('reload-devices')
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
try {
await window.http.get(`/app/reconnect`)
} catch (error) {
if (error.response) {
throw Error(error.response.data.message)
}
throw Error(error.message)
}
}
},
template: `
<div class="green card" @click="handleSubmit" style="cursor: pointer">
<div class="content">
<div class="header">Reconnect</div>
<div class="description">
Reconnect to whatsapp server, please do this if your api doesn't work or your application is down or
restart
</div>
</div>
</div>
`
}

111
src/views/components/MessageReact.js

@ -0,0 +1,111 @@
export default {
name: 'ReactMessage',
data() {
return {
type: 'user',
phone: '',
message_id: '',
emoji: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalMessageReaction').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalMessageReaction').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
const payload = {phone: this.phone_id, emoji: this.emoji}
let response = await window.http.post(`/message/${this.message_id}/reaction`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.message_id = '';
this.emoji = '';
this.type = 'user';
},
},
template: `
<div class="red card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui red right ribbon label">Message</a>
<div class="header">React Message</div>
<div class="description">
any message in private or group chat
</div>
</div>
</div>
<!-- Modal MessageReaction -->
<div class="ui small modal" id="modalMessageReaction">
<i class="close icon"></i>
<div class="header">
React Message
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Message ID</label>
<input v-model="message_id" type="text" placeholder="Please enter your message id"
aria-label="message id">
</div>
<div class="field">
<label>Emoji</label>
<input v-model="emoji" type="text" placeholder="Please enter emoji"
aria-label="message id">
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

103
src/views/components/MessageRevoke.js

@ -0,0 +1,103 @@
export default {
name: 'Message',
data() {
return {
type: 'user',
phone: '',
message_id: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalMessageRevoke').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalMessageRevoke').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
const payload = {phone: this.phone_id}
let response = await window.http.post(`/message/${this.message_id}/revoke`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.message_id = '';
this.type = 'user';
},
},
template: `
<div class="red card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui red right ribbon label">Message</a>
<div class="header">Revoke Message</div>
<div class="description">
any message in private or group chat
</div>
</div>
</div>
<!-- Modal MessageRevoke -->
<div class="ui small modal" id="modalMessageRevoke">
<i class="close icon"></i>
<div class="header">
Revoke Message
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label> Message ID</label>
<input v-model="message_id" type="text" placeholder="Please enter your message id"
aria-label="message id">
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

83
src/views/components/MessageUpdate.js

@ -2,80 +2,73 @@ export default {
name: 'UpdateMessage',
data() {
return {
update_type: 'user',
update_phone: '',
update_message_id: '',
update_new_message: '',
update_loading: false,
type: 'user',
phone: '',
message_id: '',
new_message: '',
loading: false,
}
},
computed: {
update_phone_id() {
return this.update_type === 'user' ? `${this.update_phone}@${window.TYPEUSER}` : `${this.update_phone}@${window.TYPEGROUP}`
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
messageEditModal() {
$('#modalMessageEdit').modal({
openModal() {
$('#modalMessageUpdate').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async messageEditProcess() {
async handleSubmit() {
try {
let response = await this.messageEditApi()
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalMessageEdit').modal('hide');
$('#modalMessageUpdate').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
messageEditApi() {
return new Promise(async (resolve, reject) => {
async submitApi() {
this.loading = true;
try {
this.update_loading = true;
const payload = {phone: this.phone_id, message: this.new_message}
const payload = {
phone: this.update_phone_id,
message: this.update_new_message
}
let response = await http.post(`/message/${this.update_message_id}/update`, payload)
this.messageEditReset();
resolve(response.data.message)
let response = await window.http.post(`/message/${this.message_id}/update`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
reject(error.response.data.message)
} else {
reject(error.message)
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.update_loading = false;
this.loading = false;
}
})
},
messageEditReset() {
this.update_type = 'user';
this.update_phone = '';
this.update_message_id = '';
this.update_new_message = '';
this.update_loading = false;
handleReset() {
this.type = 'user';
this.phone = '';
this.message_id = '';
this.new_message = '';
this.loading = false;
},
},
template: `
<div class="red card" @click="messageEditModal()" style="cursor: pointer">
<div class="red card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui red right ribbon label">Message</a>
<div class="header">Edit Message</div>
<div class="header">Update Message</div>
<div class="description">
Update your sent message
</div>
</div>
</div>
<!-- Modal MessageEdit -->
<div class="ui small modal" id="modalMessageEdit">
<!-- Modal MessageUpdate -->
<div class="ui small modal" id="modalMessageUpdate">
<i class="close icon"></i>
<div class="header">
Update Message
@ -84,32 +77,32 @@ export default {
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="update_type" v-model="update_type" aria-label="type">
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="update_phone" type="text" placeholder="6289..."
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="update_phone_id" disabled aria-label="whatsapp_id">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Message ID</label>
<input v-model="update_message_id" type="text" placeholder="Please enter your message id"
<input v-model="message_id" type="text" placeholder="Please enter your message id"
aria-label="message id">
</div>
<div class="field">
<label>New Message</label>
<textarea v-model="update_new_message" type="text" placeholder="Hello this is your new message text, you can edit before 15 minutes after sent."
<textarea v-model="new_message" type="text" placeholder="Hello this is your new message text, you can edit before 15 minutes after sent."
aria-label="message"></textarea>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.update_loading}"
@click="messageEditProcess">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Update
<i class="send icon"></i>
</div>

107
src/views/components/SendAudio.js

@ -0,0 +1,107 @@
export default {
name: 'Send',
data() {
return {
phone: '',
type: 'user',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalAudioSend').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalAudioSend').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let payload = new FormData();
payload.append("phone", this.phone_id)
payload.append("audio", $("#file_audio")[0].files[0])
const response = await window.http.post(`/send/audio`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.type = 'user';
$("#file_audio").val('');
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Audio</div>
<div class="description">
Send audio to user or group
</div>
</div>
</div>
<!-- Modal SendAudio -->
<div class="ui small modal" id="modalAudioSend">
<i class="close icon"></i>
<div class="header">
Send Audio
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field" style="padding-bottom: 30px">
<label>Audio</label>
<input type="file" style="display: none" accept="audio/*" id="file_audio"/>
<label for="file_audio" class="ui positive medium green left floated button" style="color: white">
<i class="ui upload icon"></i>
Upload
</label>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

117
src/views/components/SendContact.js

@ -0,0 +1,117 @@
export default {
name: 'SendContact',
data() {
return {
type: 'user',
phone: '',
card_name: '',
card_phone: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendContact').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
this.loading = true;
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendContact').modal('hide');
} catch (err) {
showErrorInfo(err)
} finally {
this.loading = false;
}
},
async submitApi() {
this.loading = true;
try {
const payload = {
phone: this.phone_id,
contact_name: this.card_name,
contact_phone: this.card_phone
}
let response = await window.http.post(`/send/contact`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.card_name = '';
this.card_phone = '';
this.type = 'user';
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Contact</div>
<div class="description">
Send contact to user or group
</div>
</div>
</div>
<!-- Modal SendContact -->
<div class="ui small modal" id="modalSendContact">
<i class="close icon"></i>
<div class="header">
Send Contact
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Contact Name</label>
<input v-model="card_name" type="text" placeholder="Please enter contact name"
aria-label="contact name">
</div>
<div class="field">
<label>Contact Phone</label>
<input v-model="card_phone" type="text" placeholder="Please enter contact phone"
aria-label="contact phone">
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

122
src/views/components/SendFile.js

@ -0,0 +1,122 @@
export default {
name: 'SendFile',
props: {
maxFileSize: {
type: String,
required: true,
}
},
data() {
return {
caption: '',
type: 'user',
phone: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendFile').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendFile').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let payload = new FormData();
payload.append("caption", this.caption)
payload.append("phone", this.phone_id)
payload.append("file", $("#file_file")[0].files[0])
let response = await window.http.post(`/send/file`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.caption = '';
this.phone = '';
this.type = 'user';
$("#file_file").val('');
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send File</div>
<div class="description">
Send any file up to
<div class="ui blue horizontal label">{{ maxFileSize }}</div>
</div>
</div>
</div>
<!-- Modal SendFile -->
<div class="ui small modal" id="modalSendFile">
<i class="close icon"></i>
<div class="header">
Send File
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Caption</label>
<textarea v-model="caption" placeholder="Type some caption (optional)..."
aria-label="caption"></textarea>
</div>
<div class="field" style="padding-bottom: 30px">
<label>File</label>
<input type="file" style="display: none" id="file_file">
<label for="file_file" class="ui positive medium green left floated button" style="color: white">
<i class="ui upload icon"></i>
Upload file
</label>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

139
src/views/components/SendImage.js

@ -0,0 +1,139 @@
export default {
name: 'SendImage',
data() {
return {
phone: '',
view_once: false,
compress: false,
caption: '',
type: 'user',
loading: false,
selected_file: null
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendImage').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendImage').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let payload = new FormData();
payload.append("phone", this.phone_id)
payload.append("view_once", this.view_once)
payload.append("compress", this.compress)
payload.append("caption", this.caption)
payload.append('image', $("#file_image")[0].files[0])
let response = await window.http.post(`/send/image`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.view_once = false;
this.compress = false;
this.phone = '';
this.caption = '';
this.type = 'user';
$("#file_image").val('');
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor:pointer;">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Image</div>
<div class="description">
Send image with
<div class="ui blue horizontal label">jpg/jpeg/png</div>
type
</div>
</div>
</div>
<!-- Modal SendImage -->
<div class="ui small modal" id="modalSendImage">
<i class="close icon"></i>
<div class="header">
Send Image
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Caption</label>
<textarea v-model="caption" type="text" placeholder="Hello this is image caption"
aria-label="caption"></textarea>
</div>
<div class="field">
<label>View Once</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="view once" v-model="view_once">
<label>Check for enable one time view</label>
</div>
</div>
<div class="field">
<label>Compress</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="compress" v-model="compress">
<label>Check for compressing image to smaller size</label>
</div>
</div>
<div class="field" style="padding-bottom: 30px">
<label>Image</label>
<input type="file" style="display: none" id="file_image" accept="image/png,image/jpg,image/jpeg"/>
<label for="file_image" class="ui positive medium green left floated button" style="color: white">
<i class="ui upload icon"></i>
Upload image
</label>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

115
src/views/components/SendLocation.js

@ -0,0 +1,115 @@
export default {
name: 'SendLocation',
data() {
return {
type: 'user',
phone: '',
latitude: '',
longitude: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendLocation').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendLocation').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
const payload = {
phone: this.phone_id,
latitude: this.latitude,
longitude: this.longitude
};
const response = await window.http.post(`/send/location`, payload);
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.latitude = '';
this.longitude = '';
this.type = 'user';
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Location</div>
<div class="description">
Send location to user or group
</div>
</div>
</div>
<!-- Modal SendLocation -->
<div class="ui small modal" id="modalSendLocation">
<i class="close icon"></i>
<div class="header">
Send Location
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Location Latitude</label>
<input v-model="latitude" type="text" placeholder="Please enter latitude"
aria-label="latitude">
</div>
<div class="field">
<label>Location Longitude</label>
<input v-model="longitude" type="text" placeholder="Please enter longitude"
aria-label="longitude">
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

118
src/views/components/SendMessage.js

@ -0,0 +1,118 @@
export default {
name: 'SendMessage',
data() {
return {
type: 'user',
phone: '',
text: '',
reply_id: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendMessage').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendMessage').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
const payload = {
phone: this.phone_id,
message: this.text,
}
if (this.reply_id !== '') {
payload.reply_id = this.reply_id;
}
let response = await window.http.post(`/send/message`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.phone = '';
this.text = '';
this.type = 'user';
this.reply_id = '';
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Message</div>
<div class="description">
Send any message to user or group
</div>
</div>
</div>
<!-- Modal SendMessage -->
<div class="ui small modal" id="modalSendMessage">
<i class="close icon"></i>
<div class="header">
Send Message
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Reply Message ID</label>
<input v-model="reply_id" type="text"
placeholder="Optional: 57D29F74B7FC62F57D8AC2C840279B5B/3EB0288F008D32FCD0A424"
aria-label="reply_id">
</div>
<div class="field">
<label>Message</label>
<textarea v-model="text" placeholder="Hello this is message text"
aria-label="message"></textarea>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

93
src/views/components/SendPoll.js

@ -3,76 +3,73 @@ export default {
name: 'SendPoll',
data() {
return {
poll_phone: '',
poll_type: 'user',
poll_loading: false,
poll_question: '',
poll_options: ['', ''],
poll_max_vote: 1,
phone: '',
type: 'user',
loading: false,
question: '',
options: ['', ''],
max_vote: 1,
}
},
computed: {
poll_phone_id() {
return this.poll_type === 'user' ? `${this.poll_phone}@${window.TYPEUSER}` : `${this.poll_phone}@${window.TYPEGROUP}`
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
sendPollModal() {
openModal() {
$('#modalSendPoll').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async sendPollProcess() {
async handleSubmit() {
try {
let response = await this.sendPollApi()
let response = await this.submitApi()
window.showSuccessInfo(response)
$('#modalSendPoll').modal('hide');
} catch (err) {
window.showErrorInfo(err)
}
},
sendPollApi() {
return new Promise(async (resolve, reject) => {
async submitApi() {
this.loading = true;
try {
this.poll_loading = true;
const payload = {
phone: this.poll_phone_id,
question: this.poll_question,
max_answer: this.poll_max_vote,
options: this.poll_options
phone: this.phone_id,
question: this.question,
max_answer: this.max_vote,
options: this.options
}
let response = await window.http.post(`/send/poll`, payload)
this.sendPollReset();
resolve(response.data.message)
const response = await window.http.post(`/send/poll`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
reject(error.response.data.message)
} else {
reject(error.message)
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.poll_loading = false;
this.loading = false;
}
})
},
sendPollReset() {
this.poll_phone = '';
this.poll_type = 'user';
this.poll_question = '';
this.poll_options = ['', ''];
this.poll_max_vote = 1;
handleReset() {
this.phone = '';
this.type = 'user';
this.question = '';
this.options = ['', ''];
this.max_vote = 1;
},
addPollOption() {
this.poll_options.push('')
addOption() {
this.options.push('')
},
deletePollOption(index) {
this.poll_options.splice(index, 1)
deleteOption(index) {
this.options.splice(index, 1)
}
},
template: `
<div class="blue card" @click="sendPollModal()" style="cursor: pointer">
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Poll</div>
@ -92,34 +89,34 @@ export default {
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="poll_type" v-model="poll_type" aria-label="type">
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="poll_phone" type="text" placeholder="6289..."
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="poll_phone_id" disabled aria-label="whatsapp_id">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Question</label>
<input v-model="poll_question" type="text" placeholder="Please enter question"
<input v-model="question" type="text" placeholder="Please enter question"
aria-label="poll question">
</div>
<div class="field">
<label>Options</label>
<div style="display: flex; flex-direction: column; gap: 5px">
<div class="ui action input" :key="index" v-for="(option, index) in poll_options">
<input type="text" placeholder="Option..." v-model="poll_options[index]"
<div class="ui action input" :key="index" v-for="(option, index) in options">
<input type="text" placeholder="Option..." v-model="options[index]"
aria-label="poll option">
<button class="ui button" @click="deletePollOption(index)" type="button">
<button class="ui button" @click="deleteOption(index)" type="button">
<i class="minus circle icon"></i>
</button>
</div>
<div class="field">
<button class="mini ui primary button" @click="addPollOption" type="button">
<button class="mini ui primary button" @click="addOption" type="button">
<i class="plus icon"></i> Option
</button>
</div>
@ -127,14 +124,14 @@ export default {
</div>
<div class="field">
<label>Max Vote</label>
<input v-model="poll_max_vote" type="number" placeholder="Max Vote"
<input v-model="max_vote" type="number" placeholder="Max Vote"
aria-label="poll max votes" min="0">
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.poll_loading}"
@click="sendPollProcess" type="button">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit" type="button">
Send
<i class="send icon"></i>
</div>

145
src/views/components/SendVideo.js

@ -0,0 +1,145 @@
export default {
name: 'SendVideo',
// define props
props: {
maxVideoSize: {
type: String,
required: true,
}
},
data() {
return {
caption: '',
view_once: false,
compress: false,
type: 'user',
phone: '',
loading: false,
}
},
computed: {
phone_id() {
return this.type === 'user' ? `${this.phone}@${window.TYPEUSER}` : `${this.phone}@${window.TYPEGROUP}`
}
},
methods: {
openModal() {
$('#modalSendVideo').modal({
onApprove: function () {
return false;
}
}).modal('show');
},
async handleSubmit() {
try {
let response = await this.submitApi()
showSuccessInfo(response)
$('#modalSendVideo').modal('hide');
} catch (err) {
showErrorInfo(err)
}
},
async submitApi() {
this.loading = true;
try {
let payload = new FormData();
payload.append("phone", this.phone_id)
payload.append("caption", this.caption)
payload.append("view_once", this.view_once)
payload.append("compress", this.compress)
payload.append('video', $("#file_video")[0].files[0])
let response = await window.http.post(`/send/video`, payload)
this.handleReset();
return response.data.message;
} catch (error) {
if (error.response) {
throw new Error(error.response.data.message);
}
throw new Error(error.message);
} finally {
this.loading = false;
}
},
handleReset() {
this.caption = '';
this.view_once = false;
this.compress = false;
this.phone = '';
this.type = 'user';
$("#file_video").val('');
},
},
template: `
<div class="blue card" @click="openModal()" style="cursor: pointer">
<div class="content">
<a class="ui blue right ribbon label">Send</a>
<div class="header">Send Video</div>
<div class="description">
Send video
<div class="ui blue horizontal label">mp4</div>
up to
<div class="ui blue horizontal label">{{ maxVideoSize }}</div>
</div>
</div>
</div>
<!-- Modal SendVideo -->
<div class="ui small modal" id="modalSendVideo">
<i class="close icon"></i>
<div class="header">
Send Video
</div>
<div class="content">
<form class="ui form">
<div class="field">
<label>Type</label>
<select name="type" v-model="type" aria-label="type">
<option value="group">Group Message</option>
<option value="user">Private Message</option>
</select>
</div>
<div class="field">
<label>Phone / Group ID</label>
<input v-model="phone" type="text" placeholder="6289..."
aria-label="phone">
<input :value="phone_id" disabled aria-label="whatsapp_id">
</div>
<div class="field">
<label>Caption</label>
<textarea v-model="caption" placeholder="Type some caption (optional)..."
aria-label="caption"></textarea>
</div>
<div class="field">
<label>View Once</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="view once" v-model="view_once">
<label>Check for enable one time view</label>
</div>
</div>
<div class="field">
<label>Compress</label>
<div class="ui toggle checkbox">
<input type="checkbox" aria-label="compress" v-model="compress">
<label>Check for compressing video to smaller size</label>
</div>
</div>
<div class="field" style="padding-bottom: 30px">
<label>Video</label>
<input type="file" style="display: none" accept="video/*" id="file_video">
<label for="file_video" class="ui positive medium green left floated button" style="color: white">
<i class="ui upload icon"></i>
Upload video
</label>
</div>
</form>
</div>
<div class="actions">
<div class="ui approve positive right labeled icon button" :class="{'loading': this.loading}"
@click="handleSubmit">
Send
<i class="send icon"></i>
</div>
</div>
</div>
`
}

1689
src/views/index.html
File diff suppressed because it is too large
View File

Loading…
Cancel
Save