Browse Source
- Split the old vcard widget to two brand new widgets : vcard4 and avatar
- Split the old vcard widget to two brand new widgets : vcard4 and avatar
- Move the location widget into the profile pagepull/16/head
20 changed files with 535 additions and 23 deletions
-
18app/assets/js/movim_utils.js
-
1app/views/conf.tpl
-
1app/views/explore.tpl
-
1app/views/help.tpl
-
1app/views/main.tpl
-
1app/views/media.tpl
-
1app/views/news.tpl
-
1app/views/node.tpl
-
9app/views/profile.tpl
-
1app/views/server.tpl
-
68app/widgets/Avatar/Avatar.php
-
26app/widgets/Avatar/avatar.css
-
93app/widgets/Avatar/avatar.js
-
49app/widgets/Avatar/avatar.tpl
-
9app/widgets/Location/Location.php
-
1app/widgets/Vcard/vcard.js
-
125app/widgets/Vcard4/Vcard4.php
-
118app/widgets/Vcard4/vcard4.tpl
-
30system/Utils.php
-
4themes/movim/css/forms.css
@ -0,0 +1,68 @@ |
|||
<?php |
|||
|
|||
/** |
|||
* @package Widgets |
|||
* |
|||
* @file Avatar.php |
|||
* This file is part of Movim. |
|||
* |
|||
* @brief A widget which display all the infos of a contact, vcard 4 version |
|||
* |
|||
* @author Timothée Jaussoin <edhelas_at_gmail_dot_com> |
|||
|
|||
* Copyright (C)2013 MOVIM project |
|||
* |
|||
* See COPYING for licensing information. |
|||
*/ |
|||
|
|||
class Avatar extends WidgetBase |
|||
{ |
|||
function WidgetLoad() |
|||
{ |
|||
$this->registerEvent('myavatarvalid', 'onAvatarPublished'); |
|||
$this->registerEvent('myavatarinvalid', 'onAvatarNotPublished'); |
|||
$this->addcss('avatar.css'); |
|||
$this->addjs('avatar.js'); |
|||
|
|||
$cd = new \modl\ContactDAO(); |
|||
$me = $cd->get($this->user->getLogin()); |
|||
$this->view->assign('me', $me); |
|||
|
|||
$this->view->assign( |
|||
'submit', |
|||
$this->genCallAjax('ajaxAvatarSubmit', "movim_form_to_json('avatarform')") |
|||
); |
|||
} |
|||
|
|||
function onAvatarPublished() |
|||
{ |
|||
RPC::call('movim_button_reset', '#avatarvalidate'); |
|||
Notification::appendNotification(t('Avatar Updated'), 'success'); |
|||
RPC::commit(); |
|||
} |
|||
|
|||
function onAvatarNotPublished() |
|||
{ |
|||
Notification::appendNotification(t('Avatar Not Updated'), 'error'); |
|||
RPC::commit(); |
|||
} |
|||
|
|||
function ajaxAvatarSubmit($avatar) |
|||
{ |
|||
$cd = new \modl\ContactDAO(); |
|||
$c = $cd->get($this->user->getLogin()); |
|||
|
|||
if($c == null) |
|||
$c = new modl\Contact(); |
|||
|
|||
$c->phototype = $avatar->phototype->value; |
|||
$c->photobin = $avatar->photobin->value; |
|||
|
|||
$c->createThumbnails(); |
|||
|
|||
$cd->set($c); |
|||
|
|||
$r = new moxl\AvatarSet(); |
|||
$r->setData($avatar->photobin->value)->request(); |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
#avatar img { |
|||
margin: 0 auto; |
|||
} |
|||
|
|||
#avatar .element #runningcam, |
|||
#avatar .element #shoot{ |
|||
display: none; |
|||
} |
|||
|
|||
#avatar .element.active #runningcam{ |
|||
display: block; |
|||
} |
|||
|
|||
#avatar .element.active #shoot{ |
|||
display: inline-block; |
|||
} |
|||
|
|||
#avatar .element.active #capture { |
|||
display: none; |
|||
} |
|||
|
|||
.squares, #snap{ |
|||
height:200px; |
|||
box-shadow: none !important; |
|||
border: 0px !important; |
|||
} |
@ -0,0 +1,93 @@ |
|||
function vCardImageResize(img) { |
|||
var canvas = document.createElement('canvas'); |
|||
|
|||
canvas.width = canvas.height = 210; |
|||
|
|||
var width = canvas.width; |
|||
var height = canvas.height; |
|||
|
|||
if (img.width == img.height) { |
|||
canvas.getContext("2d").drawImage(img, 0, 0, width, height); |
|||
} else { |
|||
minVal = Math.min(img.width, img.height); |
|||
if (img.width > img.height) { |
|||
canvas.getContext("2d").drawImage(img, (img.width - minVal) / 2, 0, minVal, minVal, 0, 0, width, height); |
|||
} else { |
|||
canvas.getContext("2d").drawImage(img, 0, (img.height - minVal) / 2, minVal, minVal, 0, 0, width, height); |
|||
} |
|||
} |
|||
|
|||
canvas.style.width = 200; |
|||
canvas.style.height = 200; |
|||
|
|||
var base64 = canvas.toDataURL('image/jpeg', 0.9); |
|||
var bin = base64.split(","); |
|||
document.querySelector('#vCardPhotoPreview').src = base64; |
|||
document.querySelector('input[name="phototype"]').value = 'image/jpeg'; |
|||
document.querySelector('input[name="photobin"]').value = bin[1]; |
|||
|
|||
function bytesToSize(bytes) { |
|||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; |
|||
if (bytes == 0) return 'n/a'; |
|||
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); |
|||
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]; |
|||
}; |
|||
|
|||
document.getElementById("picturesize").innerHTML = bytesToSize(encodeURI(base64).split(/%..|./).length - 1); |
|||
}; |
|||
|
|||
function vCardImageLoad(files) { |
|||
var f = files[0]; |
|||
if (!f.type.match(/image.*/)) { |
|||
console.log("Not a picture !"); |
|||
} else { |
|||
var reader = new FileReader(); |
|||
reader.readAsDataURL(f); |
|||
|
|||
reader.onload = function ( ev ) { |
|||
var img = new Image(); |
|||
img.src = ev.target.result; |
|||
img.onload = function() { |
|||
vCardImageResize(this); |
|||
}; |
|||
}; |
|||
}; |
|||
}; |
|||
|
|||
function showVideo(){ |
|||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; |
|||
navigator.getUserMedia({video:true, audio:false}, successCallback, errorCallback); |
|||
|
|||
movim_toggle_class('#camdiv', 'active'); |
|||
} |
|||
function successCallback(stream) { |
|||
video = document.getElementById("runningcam"); |
|||
video.src = window.URL.createObjectURL(stream); |
|||
localMediaStream = stream; // stream available to console
|
|||
|
|||
document.getElementById("shoot").addEventListener('click', snapshot, false); |
|||
} |
|||
|
|||
function errorCallback(error){ |
|||
console.log("navigator.getUserMedia error: ", error); |
|||
} |
|||
|
|||
|
|||
function snapshot() { |
|||
if (localMediaStream) { |
|||
canvas = document.querySelector("canvas"); |
|||
canvas.width = video.videoWidth; |
|||
canvas.height = video.videoHeight; |
|||
ctx = canvas.getContext('2d'); |
|||
video = document.getElementById("runningcam"); |
|||
|
|||
ctx.drawImage(video,0,0, canvas.width, canvas.height); |
|||
// "image/webp" works in Chrome 18. In other browsers, this will fall back to image/png.
|
|||
var img = new Image(); |
|||
img.src = canvas.toDataURL('image/png'); |
|||
|
|||
img.onload = function() { |
|||
vCardImageResize(this); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,49 @@ |
|||
<div class="tabelem padded" title="{$c->t('Avatar')}" id="avatar" > |
|||
<form name="avatarform" id="avatarform"> |
|||
<fieldset> |
|||
<legend>{$c->t('Avatar')}</legend> |
|||
<div class="element"> |
|||
<label for="avatar">{$c->t('Avatar')}</label> |
|||
<img id="vCardPhotoPreview" src="data:'.$me->phototype.';base64,{$me->photobin}"> |
|||
<br /><span id="picturesize" class="clean"></span><br /><br /> |
|||
|
|||
<input type="file" onchange="vCardImageLoad(this.files);"> |
|||
|
|||
<input type="hidden" name="phototype" value="{$me->phototype}"/> |
|||
<input type="hidden" name="photobin" value="{$me->photobin}"/> |
|||
</div> |
|||
|
|||
<div class="element" id="camdiv"> |
|||
<label for="url">{$c->t('Webcam')}</label> |
|||
<video id="runningcam" class="squares" autoplay></video> |
|||
<canvas style="display:none;"></canvas> |
|||
|
|||
<a |
|||
id="shoot" |
|||
class="button icon preview color green" |
|||
onclick="return false;"> |
|||
{$c->t("Cheese !")} |
|||
</a> |
|||
<a |
|||
id="capture" |
|||
class="button icon image color purple" |
|||
onclick=" |
|||
showVideo(); |
|||
return false;"> |
|||
{$c->t("Take a webcam snapshot")} |
|||
</a> |
|||
</div> |
|||
</fieldset> |
|||
|
|||
<a |
|||
onclick=" |
|||
{$submit} |
|||
movim_button_save('#avatarvalidate'); |
|||
this.value = '{$c->t('Submitting')}'; |
|||
this.className='button color orange icon loading inactive';" |
|||
class="button icon color green yes" |
|||
id="avatarvalidate" |
|||
style="float: right;" |
|||
>{$c->t('Submit')}</a> |
|||
</form> |
|||
</div> |
@ -0,0 +1,125 @@ |
|||
<?php |
|||
|
|||
/** |
|||
* @package Widgets |
|||
* |
|||
* @file Vcard4.php |
|||
* This file is part of MOVIM. |
|||
* |
|||
* @brief A widget which display all the infos of a contact, vcard 4 version |
|||
* |
|||
* @author Timothée Jaussoin <edhelas_at_gmail_dot_com> |
|||
|
|||
* Copyright (C)2013 MOVIM project |
|||
* |
|||
* See COPYING for licensing information. |
|||
*/ |
|||
|
|||
class Vcard4 extends WidgetBase |
|||
{ |
|||
function WidgetLoad() |
|||
{ |
|||
$this->registerEvent('myvcard4valid', 'onMyVcard4Received'); |
|||
$this->registerEvent('myvcard4invalid', 'onMyVcard4NotReceived'); |
|||
|
|||
$cd = new \modl\ContactDAO(); |
|||
$me = $cd->get($this->user->getLogin()); |
|||
$this->view->assign('me', $me); |
|||
$this->view->assign('desc', trim($me->description)); |
|||
$this->view->assign('gender', getGender()); |
|||
$this->view->assign('marital', getMarital()); |
|||
|
|||
$this->view->assign( |
|||
'submit', |
|||
$this->genCallAjax('ajaxVcardSubmit', "movim_form_to_json('vcard4')") |
|||
); |
|||
|
|||
// The datepicker arrays
|
|||
$days = $months = $years = array(); |
|||
for($i=1; $i<= 31; $i++) { |
|||
if($i < 10){ |
|||
$j = '0'.$i; |
|||
} else { |
|||
$j = (string)$i; |
|||
} |
|||
$days[$i] = $j; |
|||
} |
|||
for($i=1; $i<= 12; $i++) { |
|||
if($i < 10){ |
|||
$j = '0'.$i; |
|||
} else { |
|||
$j = (string)$i; |
|||
} |
|||
$m = getMonths(); |
|||
|
|||
$months[$j] = $m[$i]; |
|||
} |
|||
for($i=date('o'); $i>= 1920; $i--) { array_push($years, $i); } |
|||
|
|||
$this->view->assign('days', $days); |
|||
$this->view->assign('months', $months); |
|||
$this->view->assign('years', $years); |
|||
} |
|||
|
|||
function onMyVcard4Received() |
|||
{ |
|||
RPC::call('movim_button_reset', '#vcard4validate'); |
|||
Notification::appendNotification(t('Profile Updated'), 'success'); |
|||
RPC::commit(); |
|||
} |
|||
|
|||
function onMyVcard4NotReceived() |
|||
{ |
|||
Notification::appendNotification(t('Profile Not Updated'), 'error'); |
|||
RPC::commit(); |
|||
} |
|||
|
|||
function ajaxVcardSubmit($vcard) |
|||
{ |
|||
# Format it ISO 8601:
|
|||
if($vcard->year->value != -1 |
|||
&& $vcard->month->value != -1 |
|||
&& $vcard->day->value != -1) |
|||
$vcard->date->value = |
|||
$vcard->year->value.'-'. |
|||
$vcard->month->value.'-'. |
|||
$vcard->day->value; |
|||
|
|||
unset($vcard->year->value); |
|||
unset($vcard->month->value); |
|||
unset($vcard->day->value); |
|||
|
|||
$cd = new \modl\ContactDAO(); |
|||
$c = $cd->get($this->user->getLogin()); |
|||
|
|||
if($c == null) |
|||
$c = new modl\Contact(); |
|||
|
|||
$c->jid = $this->user->getLogin(); |
|||
|
|||
if(isset($vcard->date->value)) { |
|||
$date = strtotime($vcard->date->value); |
|||
$c->date = date('Y-m-d', $date); |
|||
} |
|||
|
|||
$c->name = $vcard->name->value; |
|||
$c->fn = $vcard->fn->value; |
|||
$c->url = $vcard->url->value; |
|||
|
|||
$c->gender = $vcard->gender->value; |
|||
$c->marital = $vcard->marital->value; |
|||
|
|||
$c->email = $vcard->email->value; |
|||
|
|||
$c->description = trim($vcard->desc->value); |
|||
|
|||
$cd = new modl\ContactDAO(); |
|||
$cd->set($c); |
|||
|
|||
$r = new moxl\Vcard4Set(); |
|||
$r->setData($vcard)->request(); |
|||
|
|||
$r = new moxl\VcardSet(); |
|||
$r->setData($vcard)->request(); |
|||
} |
|||
} |
@ -0,0 +1,118 @@ |
|||
<div class="tabelem padded" title="{$c->t('Data')}" id="vcard4" > |
|||
<form name="vcard4" id="vcard4form"> |
|||
<fieldset> |
|||
<legend>{$c->t('General Informations')}</legend> |
|||
<div class="element"> |
|||
<label for="fn">{$c->t('Name')}</label> |
|||
<input type="text" name="fn" class="content" value="{$me->fn}"> |
|||
</div> |
|||
<div class="element"> |
|||
<label for="fn">{$c->t('Nickname')}</label> |
|||
<input type="text" name="name" class="content" value="{$me->name}"> |
|||
</div> |
|||
<div class="element"> |
|||
<label for="fn">{$c->t('Email')}</label> |
|||
<input type="email" name="email" class="content" value="{$me->email}"> |
|||
</div> |
|||
|
|||
<!-- The date picker --> |
|||
|
|||
<div class="element "> |
|||
<label for="day">{$c->t('Date of Birth')}</label> |
|||
<div class="select" style="width: 33%; float: left;"> |
|||
<select name="day" class="datepicker"> |
|||
<option value="-1">{$c->t('Day')}</option> |
|||
{loop="$days"} |
|||
<option value="{$value}" |
|||
{if="$key == substr($me->date, 8)"} |
|||
selected |
|||
{/if} |
|||
>{$value}</option> |
|||
{/loop} |
|||
</select> |
|||
</div> |
|||
|
|||
<div class="select" style="width: 34%; float: left;"> |
|||
<select name="month" class="datepicker"> |
|||
<option value="-1">{$c->t('Month')}</option> |
|||
{loop="$months"} |
|||
<option value="{$key}" |
|||
{if="$key == substr($me->date,5,2)"} |
|||
selected |
|||
{/if} |
|||
>{$value}</option> |
|||
{/loop} |
|||
</select> |
|||
</div> |
|||
|
|||
<div class="select" style="width: 33%; float: left;"> |
|||
<select name="year" class="datepicker"> |
|||
<option value="-1">{$c->t('Year')}</option> |
|||
{loop="$years"} |
|||
<option value="{$value}" |
|||
{if="$value == substr($me->date,0,4)"} |
|||
selected |
|||
{/if} |
|||
>{$value}</option> |
|||
{/loop} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="element"> |
|||
<label for="gender">{$c->t('Gender')}</label> |
|||
<div class="select"> |
|||
<select name="gender"> |
|||
{loop="$gender"} |
|||
<option |
|||
{if="$key == $me->gender"} |
|||
selected |
|||
{/if} |
|||
value="{$key}">{$value}</option> |
|||
{/loop} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="element"> |
|||
<label for="marital">{$c->t('Marital Status')}</label> |
|||
<div class="select"> |
|||
<select name="marital"> |
|||
{loop="$marital"} |
|||
<option |
|||
{if="$key == $me->marital"} |
|||
selected |
|||
{/if} |
|||
value="{$key}">{$value}</option> |
|||
{/loop} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="element large"> |
|||
<label for="url">{$c->t('Website')}</label> |
|||
<input type="url" name ="url" class="content" value="{$me->url}"> |
|||
</div> |
|||
|
|||
<div class="element large"> |
|||
<label for="desc">{$c->t('About Me')}</label> |
|||
<textarea name="desc" id="desctext" class="content" onkeyup="movim_textarea_autoheight(this);">{$desc}</textarea> |
|||
</div> |
|||
</fieldset> |
|||
|
|||
<a |
|||
onclick=" |
|||
{$submit} |
|||
movim_button_save('#vcard4validate'); |
|||
this.value = '{$c->t('Submitting')}'; |
|||
this.className='button color orange icon loading merged right inactive';" |
|||
class="button icon merged right color green yes" |
|||
style="float: right;" |
|||
id="vcard4validate" |
|||
>{$c->t('Submit')}</a> |
|||
<a |
|||
onclick="document.querySelector('#vcard4form').reset();" |
|||
class="button icon no merged left color orange" |
|||
style="float: right;">{$c->t('Reset')}</a> |
|||
</form> |
|||
</div> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue