• Tidak ada hasil yang ditemukan

BAB III METODOLOGI PENELITIAN

2. Metode wawancara

4.2 Pembahasan

4.2.3 Pengujian Aplikasi

Gambar 4.16 Aplikasi mengirim file

Gambar 4.17 Penguji Menggunakan Wireshark a. Throughput

Throughput merupakan kecepatan rata rata data dalam selang waktu tertentu. Berikut adalah data statistic yang diperoleh dalam komunikasi video streaming.

Gambar 4.18 Statistics client a dan b

Dari data yang di capture maka diperoleh hasil throughput adalah sebagai berikut :

= 1.070,815 kbps

= 0.347 kbps b. Delay

Delay merupakan waktu yang dibutuhkan suatu packet untuk sampai ke tempat tujuan. Delay terjadi karena adanya sebuah antrian panjang dalam transmisi data. Berikut adalah hasil delay yang diperoleh pada komunikasi Video Streaming, yang dianalisis menggunakan Wireshark

Delay Client A = 0.483 s = 483 ms

Delay Client B = 0.471 s = 471 ms

c. Packet Loss

Paket Loss merupakan banyaknya paket yang hilang karna penuhnya kapasitas jaringan Jika packet loss besar, maka kualitas audio dan video dikirim tidak akan diterima dengan baik oleh penerima. Dari data yang diperoleh maka packet loss dapat dihitung sebagai berikut :

Packet Loss Client A X 100%

= 0

Packet Loss Client b X 100%

= 0 2. Pengujian ID Account

Pengujian ini bertujuan untuk mengetahui apakah ID Account dapat bekerja dengan sesuai yang dirancang.

No Masukan ID Account Status Hasil

1 Client A Berfungsi User invite nama ID 2 Client B Berfungsi User invite nama ID

Tabel 4.1 Pengujian ID Account 3. Pengujian User Invite

Pengujian ini bertujuan untuk mengetahui apakah client bisa untuk join bersama dalam satu Video Conference.

No Masukan ID Account Status Hasil

1 Client A Berfungsi User invite nama ID Copy URL

2 Client B Berfungsi User invite nama ID Copy URL

Tabel 4.2 Pengujian User Invite 4. Pengujian Chatting dan kirim file

Pengujian ini bertujuan untuk mengetahui apakah client 1 dan client 2 dapat bersama untuk melakukan chatting dan mengirim file.

No Masukan ID

Account

Chat Kirim File Hasil

1 Client A Berfungsi Berfungsi Dapat chatting dan kirim file satu sama lain.

2 Client B Berfungsi Berfungsi Dapat chatting dan kirim file satu sama lain.

Tabel 4.3 Pengujian Chatting dan Kirim File 5. Pengujian Audio dan Video streaming

No Masukan ID

Account

Audio Video Hasil

1 Client A Berfungsi Berfungsi Dapat mendengar audio dan video streaming satu sama lain.

2 Client B Berfungsi Berfungsi Dapat mendengar audio dan video

streaming satu sama lain..

Tabel 4.4 Pengujian Audio dan Video streaming.

80 BAB V

KESIMPULAN DAN SARAN

5.1 Kesimpulan

Telah berhasil dilakukan pengujian terhadap rancang bangun aplikasi Video Conference berbasis web. Aplikasi ini dapat memudahkan pegawai untuk melakukan Video Conference tanpa harus memikiran batasan waktu.

Sehingga pegawai tidak perlu takut atau kelupaan, terburu buru dalam melakukan Video Conference karena masalah waktu yang terbatas.

5.2 Saran

Rancang bangun Aplikasi Video Conference berbasis web. Berdasarkan hasil yang peroleh disadari bahwa rancang bangun Video Conference ini masih jauh dari kata sempurna dan masih memerlukan pengembangan software tambahan agar terciptanya aplikasi web yang lebih baik selain itu, aplikasi yang dibuat hanyalah prototype sehingga penggunaan aplikasi ini pun belum maksimal. Untuk itu, beberapa saran berikut sebagai pengembangan aplikasi :

1. Rancang bangun aplikasi berbentuk prototype ini dapat dibuat lebih canggih lagi agar manfaatnya dapat langsung dirasakan.

2. Rancang bangun aplikasi ini bisa dikembangkan menggunakan aplikasi android agar terlihat lebih canggih dan terlihat seperti aplikasi yang sudah canggih terlebih dahulu.

81

Desy Damasari Nazilah, M. Nanak Zakaria, Aisah. (2017,Mei 1) PERENCANAAN DAN

IMPLEMENTASI PROTOKOL VIDEO CONVERENCE PADA KELUARGA

NARAPIDANA PENGHUNI LEMBAGA PEMASYARAKATAN

MENGGUNAKAN SMARTPHONE, 1-7

Rizki Ainanda, Edy Victor Haryanto. (2016, Januari) RANCANG BANGUN APLIKASI E-

MEETING MENGGUNAKAN WEBRTC (WEB REAL TIME

COMMUNICATION), 1-8

Rahadiyan Yuniar Rahmanda, Eko Sakti Pramukantoro, Widhi Yahya. (2018,Juli)

IMPLEMENTASI KELAS VIRTUAL FILKOM UNIVERSITAS

BRAWIJAYA DENGAN MEMANFAATKAN TEKNOLOGI WEBRTC (WEB REAL-TIME COMMUNICATION ), 1-9

Cahyo Handoko Putra. (2013, SEPTEMBER) ANALISIS DAN PERANCANGAN SISTEM APLIKASI VIDEO CONFERENCE DAN SURVEILANS PADA PT.

KARYA SEPAKAT KITA PONOROGO

Dutton, Sam. (2014). Getting Started with WebRTC. Internet:

http://www.html5rocks.com/en/tutorials/webrtc/basics/

Video Conferencing dan MPEG, Elektro Indonesia Telekomunikasi, 1997 Heriman, Wilidarmo dan Gunardi 2007, Video Steaming

Aditya. 2017. Pengertian dan Keunggulan dari TCP IP adalah diambil dari:https//devjurnal.com/pengertian-dan-keunggulan-tcp-ip-adalah/. (8 November 2017).

Varianto, E., & Mohammad Badrul. (2015). Implementasi Virtual Private Network Dan Proxy Server Menggunakan Clear Os Pada Pt.Valdo International. Jurnal Teknik Komputer Amik Bsi, 1(1), 55–56.

Sofana, Iwan. 2013. Membangun Jaringan Komputer : Mudah membuat Jaringan Komputer (Wire & Wireless) untuk pengguna Windows dan Linux. Bandung:

Informatika.

Thomhert. “WebRTC - Audio/Video Conference berbasis Web.” Internet:

http://codesaya.com/a/WebRTC-audiovideo-conference-ber-fbmyebpjxi/, Aug. 15, 2015 [Sept. 25, 2015].

82

Hasyim Nurlaila, Nur Aeni Hidayah, Sarwoto Wijoyo Latisuro, 2014. Rancang Bangun Sistem Informasi Koperasi Berbasis Web pada Koperasi Warga Baru MTS N 17.

Jakarta. “Jurnal dari Sistem Informasi” , ISSN 1979-0767. 7(2) : 1-11.

Widodo, C., Yana, M., & Agung, H. (2018, April). implementasi topologi hybrid untuk pengoptimalan alpikasi EDMSpada projek office PT PHE ONJW. Jurnal Teknik Informatika, 11, 1-12

Purnomo, R. T., & Kurniawan, M. T. (2015, JANUARY 1). ANALISIS DAN DESAIN KEAMANAN JARINGAN KOMPUTER DENGAN METODE NETWORK DEELOPMENT LIFE CYLE (STUDI KASUS: UNIVERSITAS TELKOM).

JURNAL REKAYASA DAN SISTEM INDUSTRI, II, 1-7.

Indrajani. 2014. Database Systems: Case Study All in One. Jakarta:Elex Media Komputindo.

Kristanto, Andri. 2010. Kupas Tuntas PHP dan MySQL. Klaten: Cable Book.

Fowler, Martin .2005. UML Distill 3th Ed: Panduan Singkat Bahasa Permodelan Objek Standar. Yogyakarta: Andi.

Wicaksono, Aloysius Sigit. 2011. Pemograman Web Aplikatif dengan Java. Jakarta: PT Elexmedia komputindo.

FAJRIN, R. (2017). Pengembangan Sistem Informasi Geografis Berbasis Node.JS untuk Pemetaan Mesin dan Tracking Engineer dengan Pemanfaatan Geolocation pada PT IBM Indonesia. Jurnal Informatika, 11(2), 33–40.

https://doi.org/10.26555/jifo.v11i2.a6090

Pilone, Dan dan Pitman, Neil. 2005. UML 2.0 in Nutshell. California : O'Reilly Media, 2005.

83

84 Package.json

{

"name": "zoom-clone", "version": "1.0.0", "description": "", "main": "server.js", "scripts": {

"test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js"

},

"keywords": [], "author": "", "license": "ISC", "dependencies": { "ejs": "^3.1.5", "express": "^4.17.1", "formidable": "^1.2.2", "multer": "^1.4.2", "mv": "^2.1.1", "peer": "^0.5.3", "socket.io": "^2.3.0", "uuid": "^8.3.0", "vm": "^0.1.0"

} }

Server.JS

const express = require("express");

const app = express();

const server = require("http").Server(app);

const { v4: uuidv4 } = require("uuid");

const io = require("socket.io")(server);

const http = require("http");

// Peer

var fs = require('fs');

var formidable = require('formidable');

//var mv = require('mv');

const { ExpressPeerServer } = require("peer");

85 });

app.set("view engine", "ejs");

app.use(express.static("public"));

app.use("/peerjs", peerServer);

app.get("/", (req, rsp) => { rsp.redirect(`/${uuidv4()}`);

});

app.get("/:room", (req, res) => {

res.render("room", { roomId: req.params.room });

});

app.post("/fileupload", (req, res) => { if (req.url == '/fileupload') {

var form = new formidable.IncomingForm();

form.parse(req, function (err, fields, files) { var oldpath = files.filetoupload.path;

var newpath = __dirname + "/public/upload/image/" + files.filetou pload.name;

fs.rename(oldpath, newpath, function (err) { if (err) throw err;

//res.write('File uploaded and moved!');

res.setHeader('Content-Type', 'application/json');

res.end(JSON.stringify({ result: "http://localhost:4010/upload/

image/" + encodeURI(files.filetoupload.name), file:files.filetoupload.nam e }));

//$("#chat_message").val(__dirname + "/public/upload/image/" + files.filetoupload.name);

//res.end();

});

});

} } );

io.on("connection", (socket) => {

socket.on("join-room", (roomId, userId) => { socket.join(roomId);

socket.to(roomId).broadcast.emit("user-connected", userId);

socket.on("message", (message) => {

io.to(roomId).emit("createMessage", message);

86 });

server.listen(process.env.PORT || 4010);

room.ejs

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial- scale=1.0" />

<title>Video Conference</title>

<link

rel="stylesheet"

href="https://stackpath.bootstrapcdn.com/font- awesome/4.7.0/css/font-awesome.min.css"

/>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/boo tstrap.min.css" rel="stylesheet" integrity="sha384-

EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossor igin="anonymous">

<link rel="stylesheet" href="style.css" />

<script src="https://unpkg.com/[email protected]/dist/peerjs.min.js"></scr ipt>

<script src="https://cdnjs.cloudflare.com/ajax/libs/peerjs/1.3.1/peer js.min.js.map"></script>

<script src="/socket.io/socket.io.js"></script>

<script>

const ROOM_ID = "<%= roomId %>";

</script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.mi n.js"></script>

<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/u md/popper.min.js" integrity="sha384-

IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossor igin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/boo tstrap.min.js" integrity="sha384-

cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossor igin="anonymous"></script>

</head>

87 <div class="main__left maximize">

<div class="container-popup">

<div class="box-popup">

<span class="popup">VIDEO CONFERENCE</span>

</div>

</div>

<div class="main__videos">

<div id="video-grid"></div>

</div>

<div class="main__controls">

<div class="main__controls_block">

<div

class="main__controls_button"

id="muteButton"

onclick="muteUnmute()"

>

<i class="fa fa-microphone"></i>

<span>Mute</span>

</div>

<div

class="main__controls_button"

id="playPauseVideo"

onclick="playStop()"

>

<i class="fa fa-video-camera"></i>

<span>Pause Video</span>

</div>

</div>

<div class="main__controls_block">

<div class="main__controls_button" id="chat-account">

<i class="fa fa-comment"></i>

<span>Chat</span>

</div>

<div class="main__controls_button inviteAccount" id="invite- account"

data-bs-toggle="modal" data-bs-target="#exampleModal">

<i class="fa fa-user-plus"></i>

<span class="">Invite</span>

</div>

</div>

</div>

</div>

<div class="main__right">

88 </div>

<div class="main__chat__window" id="main__chat__window">

<ul class="messages" id="all_messages"></ul>

</div>

<div class="main__message_container">

<label for="file">

<i class="fa fa-sticky-note icon"></i>

<form action="fileupload" id="formFile" style="display:none;"

method="post" enctype="multipart/form-data">

<input type="file" id="file" onchange="savePhoto(this);"

name="filetoupload">

<input type="submit" id="submitFile" value="Upload">

</form>

</label>

<input

type="text"

id="chat_message"

placeholder="Type message here.."

/>

</div>

</div>

<!-- Modal -->

<div class="modal fade" style="overflow:hidden" id="exampleModal" t abindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">

<div class="modal-dialog">

<div class="modal-content">

<div class="modal-header">

<h5 class="modal-

title" id="exampleModalLabel"><span class="accountName"></span> Room Meet ing</h5>

<button type="button" class="btn-close" data-bs- dismiss="modal" aria-label="Close"></button>

</div>

<div class="modal-body">

<div class="input-group flex-nowrap">

<span class="input-group-text" id="addon- wrapping">Account Name</span>

<input type="text" id="accountName" class="form- control" placeholder="Username" aria-label="Username" aria- describedby="addon-wrapping">

</div>

<div class="input-group flex-nowrap">

<span class="input-group-

text" style="width: 130px;" id="addon-wrapping">Invite Link</span>

89

control" placeholder="Username" aria-label="Username" aria- describedby="addon-wrapping">

</div>

</div>

<div class="modal-footer" style="border:0">

<button type="button" onclick="copyUrl();" style="backgroun d:transparent;border:1px solid #fff;" class="btn btn-

primary">Copy URL</button>

</div>

</div>

</div>

</div>

<div class="modal fade" style="display:block;opacity:1;overflow:hid den" id="accountModal" tabindex="-1" aria-

labelledby="exampleModalLabel" aria-hidden="true">

<div class="modal-dialog">

<div class="modal-content">

<div class="modal-header">

<h5 class="modal-

title" id="exampleModalLabel">Create Account ID</h5>

<button type="button" class="btn-close" data-bs- dismiss="modal" aria-label="Close"></button>

</div>

<div class="modal-body">

<div class="input-group flex-nowrap">

<span class="input-group-text" id="addon- wrapping">ID Account</span>

<input type="text" autocomplete="off" id="input- username" style="color:#fff;background:transparent;border-

bottom:1px solid #fff;border-radius:0;" value="" class="form- control" placeholder="Username" aria-label="Username" aria- describedby="addon-wrapping">

</div>

</div>

<div class="modal-footer" style="border:0">

<button type="button" onclick="sendAccount();" style="backg round:transparent;border:1px solid #fff;" class="btn btn-

primary">Send</button>

</div>

</div>

</div>

</div>

</div>

<script src="script.js"></script>

90

$('#chat-account').on('click',function(){

if($(this).attr('data-click-state') == 1) { $(".main__right").removeClass("active");

$(".main__left").addClass("maximize");

$(".main__left").removeClass("minimize");

$(this).attr('data-click-state', 0);

}else {

$(".main__right").addClass("active");

$(".main__left").addClass("minimize");

$(".main__left").removeClass("maximize");

$(this).attr('data-click-state', 1);

} });

})

</script>

</body>

</html>

Script.js

const webSocket = new WebSocket("ws://192.168.8.2:4010") const socket = io("/");

const chatInputBox = document.getElementById("chat_message");

const all_messages = document.getElementById("all_messages");

const main__chat__window = document.getElementById("main__chat__window");

const videoGrid = document.getElementById("video-grid");

const myVideo = document.createElement("video");

myVideo.muted = true;

var peer = new Peer(undefined, { path: "/peerjs",

host: "/", port: "4010", });

let localstream let peerConn

let myVideoStream;

let username

function sendUsername() {

username = document.getElementById("username-input").value

91 })

}

function startCall() {

document.getElementById("video-grid") .style.display = "inline"

}

var getUserMedia =

navigator.getUserMedia ||

navigator.webkitGetUserMedia ||

navigator.mozGetUserMedia;

navigator.mediaDevices .getUserMedia({

video: true, audio: true, })

.then((stream) => {

myVideoStream = stream;

addVideoStream(myVideo, stream)

peer.on("call", (call) => { call.answer(stream);

const video = document.createElement("video");

call.on("stream", (userVideoStream) => { addVideoStream(video, userVideoStream);

});

});

socket.on("user-connected", (userId) => { connectToNewUser(userId, stream);

});

document.addEventListener("keydown", (e) => {

if (e.which === 13 && chatInputBox.value != "") { socket.emit("message", chatInputBox.value);

chatInputBox.value = "";

} });

var itr = 1

socket.on("createMessage", (msg) => { console.log(msg);

let li = document.createElement("li");

92 }else{

li.className = 'msg-ganjil';

}

li.innerHTML = msg;

all_messages.append(li);

main__chat__window.scrollTop = main__chat__window.scrollHeight;

itr = itr + 1;

});

});

peer.on("call", function (call) { getUserMedia(

{ video: true, audio: true }, function (stream) {

call.answer(stream); // Answer the call with an A/V stream.

const video = document.createElement("video");

call.on("stream", function (remoteStream) { addVideoStream(video, remoteStream);

});

},

function (err) {

console.log("Failed to get local stream", err);

} );

});

peer.on("open", (id) => {

socket.emit("join-room", ROOM_ID, id);

});

// CHAT

const connectToNewUser = (userId, streams) => { var call = peer.call(userId, streams);

console.log(call);

var video = document.createElement("video");

call.on("stream", (userVideoStream) => { console.log(userVideoStream);

addVideoStream(video, userVideoStream);

});

};

const addVideoStream = (videoEl, stream) => { videoEl.srcObject = stream;

videoEl.addEventListener("loadedmetadata", () => {

93 videoGrid.append(videoEl);

let totalUsers = document.getElementsByTagName("video").length;

if (totalUsers > 1) {

for (let index = 0; index < totalUsers; index++) {

document.getElementsByTagName("video")[index].style.width = 100 / totalUsers + "%";

} } };

const playStop = () => {

let enabled = myVideoStream.getVideoTracks()[0].enabled;

if (enabled) {

myVideoStream.getVideoTracks()[0].enabled = false;

setPlayVideo();

} else {

setStopVideo();

myVideoStream.getVideoTracks()[0].enabled = true;

} };

const muteUnmute = () => {

const enabled = myVideoStream.getAudioTracks()[0].enabled;

if (enabled) {

myVideoStream.getAudioTracks()[0].enabled = false;

setUnmuteButton();

} else {

setMuteButton();

myVideoStream.getAudioTracks()[0].enabled = true;

} };

const setPlayVideo = () => {

const html = `<i class="unmute fa fa-pause-circle"></i>

<span class="unmute">Resume Video</span>`;

document.getElementById("playPauseVideo").innerHTML = html;

};

const setStopVideo = () => {

const html = `<i class=" fa fa-video-camera"></i>

<span class="">Pause Video</span>`;

document.getElementById("playPauseVideo").innerHTML = html;

};

94 <span class="unmute">Unmute</span>`;

document.getElementById("muteButton").innerHTML = html;

};

const setMuteButton = () => {

const html = `<i class="fa fa-microphone"></i>

<span>Mute</span>`;

document.getElementById("muteButton").innerHTML = html;

};

const copyUrl = () => {

var copyText = document.getElementById("input-copy");

copyText.select();

copyText.setSelectionRange(0, 99999);

document.execCommand("copy");

alert("Copied the text: " + copyText.value);

};

const sendAccount = () => {

var accountName = $("#input-username").val();

$("#accountName").val(accountName);

$(".accountName").text(accountName+"'s");

$("#accountModal").css('display','none');

};

const savePhoto = (e) =>

{

let xhr = new XMLHttpRequest();

let formData = new FormData();

let photo = e.files[0];

formData.append("filetoupload", photo);

xhr.onreadystatechange = state => { console.log(xhr.status); } // err h andling

xhr.timeout = 5000;

xhr.open("POST", '/fileupload');

xhr.responseType = 'json';

xhr.onload = function(e) { if (this.status == 200) {

console.log('response', this.response); // JSON response $("#chat_message").val("<a class='link-

msg' onclick=window.open('"+this.response.result+"')><i class='fa fa- file' style='margin-right:5px;'></i>"+this.response.file+"</a>");

} };

xhr.send(formData);

}

95

document.getElementById("formFile").submit();

}

Style.css

@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap

");

* {

margin: 0;

padding: 0;

box-sizing: border-box;

} html, body {

height: 100%;

font-family: "Roboto", sans-serif;

}

.modal-title{

font-weight: bold;

font-size: 17px !important;

}

#video-grid { display: flex;

justify-content: center;

height: 100%;

width: 100%;

align-items: center;

flex-wrap: wrap;

overflow-y: auto;

}

video {

display: block;

flex: 1;

object-fit: cover;

border: 5px solid #000;

max-width: 600px;

}

.main {

height: 100%;

display: flex;

}

.main__left { flex: 0.8;

96 position:relative;

}

.main__right { flex: 0.2;

display: none;

flex-direction: column;

background-color: #242324;

border-left: 1px solid #3d3d42;

}

.main__videos { flex-grow: 1;

background-color: #000;

display: flex;

align-items: center;

justify-content: center;

}

.main__controls { display: flex;

background-color: #1c1e20;

color: #d2d2d2;

padding: 5px;

justify-content: space-between;

}

.main__controls_block { display: flex;

}

.main__controls_button { display: flex;

flex-direction: column;

cursor: pointer;

padding: 10px;

justify-content: center;

align-items: center;

min-width: 80px;

transition: all 0.3s ease-in-out;

border-radius: 10px;

margin: 5px;

}

.main__controls_button span { margin-top: 10px;

display: block;

}

.main__controls_button:hover { background-color: #34383b;

}

97 }

.inviteAccount {

background-color: #299c29;

color: #fff;

}

.main__header { color: #f5f5f5;

text-align: center;

padding: 20px;

background: #fff;

border-bottom: 1px solid #e1e1e1;

}

.main__header h6{

color: #555;

font-size: 16px;

font-weight: bold;

}

.main__chat__window { flex-grow: 1;

overflow: auto;

padding: 20px 20px 0 20px;

background: #fff;

}

.main__message_container { padding: 22px 11px;

display: flex;

background: #fff;

border-top: 1px solid #e1e1e1;

position: relative;

}

.main__message_container input { flex-grow: 1;

background-color: transparent;

border: none;

color: #555;

user-select: none;

outline: none;

font-size: 14px;

}

.main__message_container .icon{

color:#bcbcbc;

position: absolute;

right: 10px;

top: 10px;

cursor: pointer;

98 color:#fff;

font-size:14px;

}

.main__message_container .icon:hover{

color:#555;

transition: 0.5s all;

}

#all_messages li { color: #fff;

list-style: none;

border-bottom: 1px solid #3d3d42;

padding: 10px 0;

}

.unmute { color: red;

}

.modal-dialog{

height:100%;

border:0;

}

.modal-dialog .modal-content{

background-color: rgba(0,0,0,0.7);

position: absolute;

bottom: 20px;

}

.modal-header{

border: 0;

}

.modal-header h5{

color:#fff;

font-size:18px;

}

.modal-body label{

color:#fff;

}

.modal-body .input-group-text{

background: transparent;

border: 0;

color: #999;

}

.modal-body input{

background: transparent;

border: 0;

color: #fff;

}

Dokumen terkait