Users ready

This commit is contained in:
2017-12-29 14:44:18 +01:00
parent f73e20d0bc
commit cb0567d3f3
32 changed files with 1298 additions and 201 deletions
+19
View File
@@ -0,0 +1,19 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 27/12/2017
* Time: 15:17
*/
$config['charset'] = 'iso-8859-1';
$config['protocol'] = getenv( 'PROTOCOL' );
$config['smtp_host'] = getenv( 'SMTP_HOST' );
$config['smtp_user'] = getenv( 'SMTP_USER' );
$config['smtp_pass'] = getenv( 'SMTP_PASS' );
$config['smtp_port'] = getenv( 'SMTP_PORT' );
@@ -0,0 +1,67 @@
<?php
/**
* Created by Pensare Software.
* Customer: Theo Weijmer
* Date: 25/12/2017
* Time: 10:11
*/
class customersController extends MY_Controller {
public function __construct()
{
parent::__construct();
$models = [];
$libraries = [];
$this->load->model( $models );
$this->load->library( $libraries );
}
public function index()
{
}
public function getAllCustomers( $archive = 'F' )
{
$users = Customer::getAllCustomers( $archive );
$this->json( $users );
}
public function saveCustomer()
{
$userValidation = new CustomerValidation();
if ( ! $userValidation->getValidationResult() )
return $this->json( [
'success' => FALSE, 'messages' => $userValidation->getErrorMessages()] );
$user = $this->input->post();
$userID = $user['id'];
unset( $user['id'] );
$userID = Customer::saveCustomer( $userID, $user );
$this->json( ['success' => TRUE, 'userID' => $userID] );
}
public function archiveCustomer( $userID, $status )
{
Customer::whereId( $userID )->update( ['archive' => $status] );
}
public function removeCustomer( $userID )
{
$removeCustomer = new RemoveCustomer( $userID );
if ( $removeCustomer->getAllowDelete() === FALSE ) return $this->json( ['result' => FALSE] );
Customer::removeCustomer( $userID );
$this->json( ['result' => TRUE] );
}
}
@@ -37,20 +37,63 @@ class usersController extends MY_Controller {
if ( ! $userValidation->getValidationResult() )
return $this->json( [
'success'=> false, 'messages' =>$userValidation->getErrorMessages()] );
'success' => FALSE, 'messages' => $userValidation->getErrorMessages()] );
$user = $this->input->post();
$userID = $user['id'];
unset($user['id']);
unset( $user['id'] );
if( $userID == 0 )
{
createNewUser();
}
if ( $userID == 0 ) $user = $this->newUser( $user );
$userID = User::saveUser( $userID, $user);
$user['role'] = empty( $user['role'] ) ? NULL : $user['role'];
$this->json( ['success' => TRUE] );
$userID = User::saveUser( $userID, $user );
$this->json( ['success' => TRUE, 'userID' => $userID] );
}
public function archiveUser( $userID, $status )
{
User::whereId( $userID )->update( ['archive' => $status] );
}
public function removeUser( $userID )
{
$removeUser = new RemoveUser( $userID );
if ( $removeUser->getAllowDelete() === FALSE ) return $this->json( ['result' => FALSE] );
User::removeUser( $userID );
$this->json( ['result' => TRUE] );
}
private function newUser( $user )
{
$userCreation = new UserCreation( $user );
$user = $userCreation->getUser();
$password = $userCreation->getPassword();
$this->sendWelcomeEmail( $user, $password );
return $user;
}
private function sendWelcomeEmail( $user, $password )
{
$this->load->library( 'email' );
$html = $this->load->view( 'emails/welcome_email', [
'password' => $password, 'user' => $user], TRUE );
$this->email->from( 'noreply@debeleidsonderzoekers.nl', 'DBOIS' );
$this->email->to( $user['email'] );
$this->email->subject( 'Wachtwoord DBOIS' );
$this->email->message( $html );
$this->email->send();
}
}
@@ -8,8 +8,8 @@
class PasswordRecipe {
private $nakedPassword = false;
private $salt = false;
private $password = FALSE;
private $salt = FALSE;
private $saltedPassword;
public function __construct()
@@ -17,9 +17,24 @@ class PasswordRecipe {
$this->handle();
}
public function setNakedPassword( $nakedPassword )
public function getPassword()
{
$this->nakedPassword = $nakedPassword;
return $this->password;
}
public function getSalt()
{
return $this->salt;
}
public function getSaltedPassword()
{
return $this->saltedPassword;
}
public function setPassword( $password )
{
$this->password = $password;
}
public function setSalt( $salt )
@@ -29,52 +44,55 @@ class PasswordRecipe {
private function handle()
{
$this->checkNakedPassword();
$this->checkPassword();
$this->checkSalt();
$this->setSaltedPassword();
}
private function checkNakedPassword()
private function checkPassword()
{
if( ! $this->nakedPassword ) $this->createNakedPassword();
if ( ! $this->password ) $this->createPassword();
if( strlen($this->nakedPassword) < 6 ) return;
if ( strlen( $this->password ) < 6 ) return;
}
private function checkSalt()
{
if( ! $this->salt ) $this->createSalt();
if ( ! $this->salt ) $this->createSalt();
}
private function createNakedPassword()
private function createPassword()
{
$pass = $this->getRandomString(8);
$pass = $this->getRandomString( 8 );
$this->nakedPassword = $pass;
$this->password = $pass;
}
private function createSalt()
{
$salt = $this->getRandomString(8);
$salt = $this->getRandomString( 18 );
$this->salt = $salt;
$this->salt = sha1($salt);
}
private function setSaltedPassword()
{
$this->saltedPassword = sha1($this->)
$this->saltedPassword = sha1( sha1( $this->password ) . $this->salt );
}
private function getRandomString( $length=8 )
private function getRandomString( $length = 8 )
{
$rand = '';
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
$alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
for ($i = 0; $i < $length; $i++) {
$n = rand(0, $alphaLength);
$rand.= $alphabet[$n];
$alphaLength = strlen( $alphabet ) - 1; //put the length -1 in cache
for ( $i = 0; $i < $length; $i ++ )
{
$n = rand( 0, $alphaLength );
$rand .= $alphabet[ $n ];
}
return $rand;
}
}
}
@@ -0,0 +1,36 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 27/12/2017
* Time: 17:45
*/
class RemoveUser {
private $userID;
private $allowDelete=FALSE;
public function __construct( $userID )
{
$this->setUserID($userID);
$this->handle();
}
public function getAllowDelete()
{
return $this->allowDelete;
}
private function setUserID( $userID )
{
$this->userID = $userID;
}
private function handle()
{
//$this->checkIfUserHasProjects();
}
}
@@ -0,0 +1,72 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 27/12/2017
* Time: 14:10
*/
class UserCreation {
private $user;
private $passWordRecipe;
private $password;
private $saltedPassword;
private $salt;
public function __construct( $user )
{
$this->setUser( $user );
$this->handle();
}
public function getUser()
{
return $this->user;
}
public function getPassword()
{
return $this->password;
}
private function setUser( $user )
{
$this->user = $user;
}
private function handle()
{
$this->passWordRecipe = new PasswordRecipe();
$this->setPassword();
$this->setSalt();
$this->setSaltedPassword();
$this->enrichUser();
}
private function setPassword()
{
$this->password = $this->passWordRecipe->getPassword();
}
private function setSalt()
{
$this->salt = $this->passWordRecipe->getSalt();
}
private function setSaltedPassword()
{
$this->saltedPassword = $this->passWordRecipe->getSaltedPassword();
}
private function enrichUser()
{
$this->user['password'] = $this->saltedPassword;
$this->user['salt'] = $this->salt;
}
}
@@ -0,0 +1,36 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 10/07/16
* Time: 13:35
*/
require_once( APPPATH . 'libraries/validation/inputValidations/BaseValidation.php' );
class CustomerValidation extends BaseValidation {
protected $validationFields = [
'name' => [
'validations' => 'required|alphaNumericSpaces',
'fieldname' => 'name'
],
'contactperson' => [
'validations' => 'required|alphaNumericSpaces',
'fieldname' => 'contactperson'
],
'email' => [
'validations' => 'email',
'fieldname' => 'email'
]
];
public function __construct()
{
parent::__construct();
$this->ci =& get_instance();
}
}
@@ -0,0 +1,18 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 15/12/2017
* Time: 19:37
*/
class Customer_model extends MY_Model {
protected $tablename = "customers";
public function __construct()
{
parent::__construct();
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ class User_model extends MY_Model {
$this->sql = "
SELECT *
FROM users
WHERE ucase( {$field} ) = '{strtoupper($fieldValue)}'
WHERE ucase( {$field} ) = '".strtoupper($fieldValue)."'
AND id != {$recordID} ";
$result = $this->get_query_row();
+1 -1
View File
@@ -27,7 +27,7 @@ class BaseModel extends Eloquent {
protected $guarded = [];
protected $hidden = ['creation_date', 'last_update_date', 'created_by', 'updated_by'];
protected $hidden = ['creation_date', 'last_update_date', 'created_by', 'updated_by', 'password', 'salt'];
protected static $oldValue;
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* Created by Pensare Software.
* Customer: Theo Weijmer
* Date: 21/12/2017
* Time: 18:04
*/
class Customer extends BaseModel {
protected $table = "customers";
public static function getAllCustomers( $archive )
{
$customers = Customer::orderBy( 'name' );
if ( $archive == 'F' ) $customers = $customers->whereArchive( 'F' );
$customers = $customers->get();
return $customers;
}
public static function saveCustomer( $customerID, $customer )
{
$customer = (array)$customer;
if( $customerID == 0)
{
$customer = Customer::create($customer);
}
else
{
$customer = Customer::whereId($customerID)->update($customer);
}
return $customer['id'];
}
public static function removeCustomer($customerID)
{
Customer::whereId($customerID)->delete();
}
}
+9 -4
View File
@@ -47,18 +47,23 @@ class User extends BaseModel {
public static function saveUser( $userID, $user )
{
$user = (array)$user;
if( $userID == 0)
{
$user = User::create($user);
}
else
{
$user = User::whereId($userID);
$user->update($user);
$user = User::whereId($userID)->update($user);
}
return $user->id;
return $user['id'];
}
public static function removeUser($userID)
{
User::whereId($userID)->delete();
}
+375
View File
@@ -0,0 +1,375 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>wachtwoord DBOIS</title>
<link href="styles.css" media="all" rel="stylesheet" type="text/css"/>
</head>
<style>
/* -------------------------------------
GLOBAL
------------------------------------- */
* {
margin: 0;
padding: 0;
font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
box-sizing: border-box;
font-size: 14px;
}
img {
max-width: 100%;
}
body {
-webkit-font-smoothing: antialiased;
-webkit-text-size-adjust: none;
width: 100% !important;
height: 100%;
line-height: 1.6;
}
/* Let's make sure all tables have defaults */
table td {
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #f6f6f6;
}
.body-wrap {
background-color: #f6f6f6;
width: 100%;
}
.container {
display: block !important;
max-width: 600px !important;
margin: 0 auto !important;
/* makes it centered */
clear: both !important;
}
.content {
max-width: 600px;
margin: 0 auto;
display: block;
padding: 20px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #fff;
border: 1px solid #e9e9e9;
border-radius: 3px;
}
.content-wrap {
padding: 20px;
}
.content-block {
padding: 0 0 20px;
}
.header {
width: 100%;
margin-bottom: 20px;
}
.footer {
width: 100%;
clear: both;
color: #999;
padding: 20px;
}
.footer a {
color: #999;
}
.footer p, .footer a, .footer unsubscribe, .footer td {
font-size: 12px;
}
/* -------------------------------------
GRID AND COLUMNS
------------------------------------- */
.column-left {
float: left;
width: 50%;
}
.column-right {
float: left;
width: 50%;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1, h2, h3 {
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
color: #000;
margin: 40px 0 0;
line-height: 1.2;
font-weight: 400;
}
h1 {
font-size: 32px;
font-weight: 500;
}
h2 {
font-size: 24px;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 14px;
font-weight: 600;
}
p, ul, ol {
margin-bottom: 10px;
font-weight: normal;
}
p li, ul li, ol li {
margin-left: 5px;
list-style-position: inside;
}
/* -------------------------------------
LINKS & BUTTONS
------------------------------------- */
a {
color: #348eda;
text-decoration: underline;
}
.btn-primary {
text-decoration: none;
color: #FFF;
background-color: #348eda;
border: solid #348eda;
border-width: 10px 20px;
line-height: 2;
font-weight: bold;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 5px;
text-transform: capitalize;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.padding {
padding: 10px 0;
}
.aligncenter {
text-align: center;
}
.alignright {
text-align: right;
}
.alignleft {
text-align: left;
}
.clear {
clear: both;
}
/* -------------------------------------
Alerts
------------------------------------- */
.alert {
font-size: 16px;
color: #fff;
font-weight: 500;
padding: 20px;
text-align: center;
border-radius: 3px 3px 0 0;
}
.alert a {
color: #fff;
text-decoration: none;
font-weight: 500;
font-size: 16px;
}
.alert.alert-warning {
background: #ff9f00;
}
.alert.alert-bad {
background: #d0021b;
}
.alert.alert-good {
background: #68b90f;
}
/* -------------------------------------
INVOICE
------------------------------------- */
.invoice {
margin: 40px auto;
text-align: left;
width: 80%;
}
.invoice td {
padding: 5px 0;
}
.invoice .invoice-items {
width: 100%;
}
.invoice .invoice-items td {
border-top: #eee 1px solid;
}
.invoice .invoice-items .total td {
border-top: 2px solid #333;
border-bottom: 2px solid #333;
font-weight: 700;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
h1, h2, h3, h4 {
font-weight: 600 !important;
margin: 20px 0 5px !important;
}
h1 {
font-size: 22px !important;
}
h2 {
font-size: 18px !important;
}
h3 {
font-size: 16px !important;
}
.container {
width: 100% !important;
}
.content, .content-wrapper {
padding: 10px !important;
}
.invoice {
width: 100% !important;
}
}
</style>
<body>
<table class="body-wrap">
<tr>
<td></td>
<td class="container" width="600">
<div class="content">
<table class="main" width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="alert alert-warning">
Wachtwoord De Beleidsonderzoeker IS
</td>
</tr>
<tr>
<td class="content-wrap">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
Hieronder vindt u uw gebruikersnaam wachtwoord om in te loggen op het
informatiesysteem van De Beleidsonderzoekers
</td>
</tr>
<tr>
<td class="content-block">
<p>
Beste <?= $user['firstname']?> <?=$user['middlename']?> <?=$user['lastname']?>
</p>
<p>
Er is voor u een account aangemaakt is het informatiesysteem van de Beleidsonderzoekers, hieronder vindt u uw gebruikersnaam en wachtwoord waarmee u kun t inloggen in het systeem.
</p>
<br />
<br />
</td>
</tr>
<tr>
<td class="content-block">
<table class="invoice">
<tr>
<td>
<table class="invoice-items" cellpadding="0" cellspacing="0">
<tr>
<td>gebruikersnaam</td>
<td class="alignright"><?= $user['username'] ?></td>
</tr>
<tr>
<td>wacthwoord</td>
<td class="alignright"><?= $password ?></td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="content-block">
<a href="<?php echo getenv('APP_URL'); ?>" class="btn-primary">
Ga naar de website
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
<td></td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,7 @@
<?php
/**
* Created by Pensare Software.
* User: Theo Weijmer
* Date: 29/12/2017
* Time: 14:17
*/
+1 -2
View File
@@ -32,9 +32,8 @@
<link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Roboto:300,400,500,300italic'>
</head>
<body class="animsition page-login-v3 layout-full">
<?php $this->load->view('specials/notify_modal'); ?>
<!-- Page -->
<?php $this->load->view('specials/notifyme_modal'); ?>
<?php $this->load->view('specials/tellme_modal'); ?>
<div class="page vertical-align text-center" data-animsition-in="fade-in" data-animsition-out="fade-out">
<div class="page-content vertical-align-middle animation-slide-top animation-duration-1">
<div class="panel" id="login-form">
+39 -13
View File
@@ -4,17 +4,17 @@
<table class="table table-sm">
<thead>
<tr>
<th>voornaam</th>
<th>achternaam</th>
<th>tussenvoegsel</th>
<th>gebruikersnaam</th>
<th>email</th>
<th>rol</th>
<th>&nbsp;</th>
<th class="table-tealish-header">voornaam</th>
<th class="table-tealish-header">achternaam</th>
<th class="table-tealish-header">tussenvoegsel</th>
<th class="table-tealish-header">gebruikersnaam</th>
<th class="table-tealish-header">email</th>
<th class="table-tealish-header">rol</th>
<th class="table-tealish-header">&nbsp;</th>
</tr>
</thead>
<tbody>
<tr data-bind="foreach:users">
<tbody data-bind="foreach:users">
<tr>
<td><span data-bind="text:lastname"></span></td>
<td><span data-bind="text:firstname"></span></td>
<td><span data-bind="text:middlename"></span></td>
@@ -22,19 +22,45 @@
<td><span data-bind="text:email"></span></td>
<td><span data-bind=""></span></td>
<td>
<i class="icon fa-edit greenish" title="wijzig"></i>
<i class="icon fa-archive blueish" title="archiveer"></i>
<i class="icon fa-trash redish" title="verwijder"></i>
<i class="icon fa-edit pointer" title="wijzig" data-bind="click:$root.editUser"></i>
<!-- ko if:archive == 'F' -->
<i class="icon fa-archive pointer" title="archiveer"
data-bind="click:$root.archiveUser"></i>
<!-- /ko -->
<!-- ko if:archive != 'F' -->
<i class="icon fa-minus-circle redish pointer" title="archiveer"
data-bind="click:$root.archiveUser"></i>
<!-- /ko -->
<i class="icon fa-trash redish pointer" title="verwijder"
data-bind="click:$root.removeUser"></i>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="7">
<td colspan="5" class="">
<button class="btn btn-primary btn-round btn-sm" data-bind="click:newUser">
nieuwe gebruiker
</button>
</td>
<td colspan="2" class="">
<div class="row form-horizontal">
<label class="col-md-4 form-control-label">archief</label>
<div class="col-md-8">
<div class="onoffswitch" data-bind="click:toggleArchive">
<input type="checkbox"
name="onoffswitch"
class="onoffswitch-checkbox"
data-bind="checked:archive"
id="myonoffswitch">
<label class="onoffswitch-label" for="myonoffswitch">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
</div>
</div>
</td>
</tr>
</tfoot>
+4 -5
View File
@@ -8,11 +8,10 @@
<link rel="stylesheet" href="css/vendor/site.min.css">
<link rel="stylesheet" href="vendor/plugins/animsition/animsition.css">
<link rel="stylesheet" href="vendor/plugins/asscrollable/asScrollable.css">
<link rel="stylesheet" href="vendor/plugins/switchery/switchery.css">
<link rel="stylesheet" href="vendor/plugins/slidepanel/slidePanel.css">
<link rel="stylesheet" href="vendor/plugins/flag-icon-css/flag-icon.css">
<link rel="stylesheet" href="css/vendor/plugins/animsition/animsition.css">
<link rel="stylesheet" href="css/vendor/plugins/asscrollable/asScrollable.css">
<link rel="stylesheet" href="css/vendor/plugins/slidepanel/slidePanel.css">
<link rel="stylesheet" href="css/vendor/plugins/flag-icon-css/flag-icon.css">
<!-- End Stylesheets VENDOR -->
<!-- Stylesheets Pensare -->
+2 -1
View File
@@ -11,7 +11,6 @@
<script src="js/vendor/ashoverscroll/jquery-asHoverScroll.js"></script>
<!-- Plugins -->
<script src="js/vendor/switchery/switchery.js"></script>
<script src="js/vendor/intro-js/intro.js"></script>
<script src="js/vendor/screenfull/screenfull.js"></script>
<script src="js/vendor/slidepanel/jquery-slidePanel.js"></script>
@@ -52,8 +51,10 @@
<script src="js/vendor/Knockout.min.js"></script>
<script src="js/lib/main.js"></script>
<script src="js/lib/modules/specials/tellmeModule.js"></script>
<script src="js/lib/modules/menuModule.js"></script>
<script src="js/lib/modules/beheer/usersModule.js"></script>
<script src="js/lib/modules/beheer/customersModule.js"></script>
<script src="js/lib/modules/modals/userModal.js"></script>
+1
View File
@@ -2,5 +2,6 @@
$this->load->view('modals/user_modal');
$this->load->view('specials/tellme_modal');
?>
@@ -1,37 +0,0 @@
<div class="modal fade" tabindex="-1" role="dialog" id="notify-me" data-bind="css:modalClass">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<!-- ko if:alert -->
<button type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
data-bind="click:close">
<span aria-hidden="true">&times;</span></button>
<!-- /ko -->
<h4 class="modal-title" data-bind="text:title"></h4>
</div>
<div class="modal-body">
<p data-bind="text:message"></p>
</div>
<div class="modal-footer">
<!-- ko if: notify -->
<button type="button"
class="btn btn-default"
data-dismiss="modal"
data-bind="click:closeNo; text:noText"></button>
<button type="button"
class="btn btn-primary"
datya-bind="click:closeYes"></button>
<!-- /ko -->
<!-- ko if:alert -->
<button type="button"
class="btn btn-primary"
data-dismiss="modal"
data-bind="click:closeOk, text:closeText"></button>
<!-- /ko -->
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
@@ -1,4 +1,4 @@
<div class="modal modal-3d-flip-vertical" tabindex="-1" role="dialog" id="notify-me" data-bind="css:modalClass">
<div class="modal modal-3d-flip-vertical" tabindex="-1" role="dialog" id="tell-me" data-bind="css:modalClass">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
@@ -8,14 +8,14 @@
</button>
</div>
<div class="modal-body">
<p data-bind="text:message"></p>
<p data-bind="html:message"></p>
</div>
<div class="modal-footer">
<!-- ko if : notify() -->
<button type="button" class="btn btn-primary"
data-bind="text:yesText; click:closeYes"></button>
<button type="button" class="btn btn-secondary" data-dismiss="modal"
data-bind="text:noText; click:closeNo"></button>
data-bind="text:yesText, click:closeYes"></button>
<button type="button" class="btn btn-secondary"
data-bind="text:noText, click:closeNo"></button>
<!-- /ko -->
<!-- ko if : ! notify() -->
<button type="button" class="btn btn-primary" data-dismiss="modal"