Ivan - Fix uploading of files

This commit is contained in:
ivan 2017-02-18 15:28:23 -03:00
parent f9ad440bf2
commit d4263d4b94
16 changed files with 106 additions and 65 deletions

View File

@ -223,26 +223,9 @@ class TicketEvent extends React.Component {
const fileName = filePath.replace(/^.*[\\\/]/, ''); const fileName = filePath.replace(/^.*[\\\/]/, '');
return ( return (
<span onClick={this.onFileClick.bind(this, filePath)}>{fileName}</span> <a href={API.getFileLink(filePath)}>{fileName}</a>
) )
} }
onFileClick(filePath) {
API.call({
path: '/system/download',
plain: true,
data: {
file: filePath
}
}).then((result) => {
let contentType = 'application/octet-stream';
let link = document.createElement('a');
let blob = new Blob([result], {'type': contentType});
link.href = window.URL.createObjectURL(blob);
link.download = filePath;
link.click();
});
}
} }
export default TicketEvent; export default TicketEvent;

View File

@ -323,6 +323,7 @@ class TicketViewer extends React.Component {
API.call({ API.call({
path: '/ticket/comment', path: '/ticket/comment',
dataAsForm: true,
data: _.extend({ data: _.extend({
ticketNumber: this.props.ticket.ticketNumber ticketNumber: this.props.ticket.ticketNumber
}, formState) }, formState)

View File

@ -3,6 +3,7 @@ import _ from 'lodash';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import i18n from 'lib-app/i18n'; import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import SessionActions from 'actions/session-actions'; import SessionActions from 'actions/session-actions';
import Form from 'core-components/form'; import Form from 'core-components/form';
@ -16,7 +17,7 @@ class AdminLoginPage extends React.Component {
return ( return (
<div className="admin-login-page"> <div className="admin-login-page">
<Widget className="admin-login-page__content"> <Widget className="admin-login-page__content">
<div className="admin-login-page__image"><img width="100%" src="/images/logo.png" alt="OpenSupports Admin Panel"/></div> <div className="admin-login-page__image"><img width="100%" src={API.getURL() + '/images/logo.png'} alt="OpenSupports Admin Panel"/></div>
<div className="admin-login-page__login-form"> <div className="admin-login-page__login-form">
<Form onSubmit={this.onSubmit.bind(this)} loading={this.props.session.pending}> <Form onSubmit={this.onSubmit.bind(this)} loading={this.props.session.pending}>
<FormField name="email" label={i18n('EMAIL')} field="input" validation="EMAIL" fieldProps={{size:'large'}} required /> <FormField name="email" label={i18n('EMAIL')} field="input" validation="EMAIL" fieldProps={{size:'large'}} required />

View File

@ -3,6 +3,7 @@ import classNames from 'classnames';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import i18n from 'lib-app/i18n'; import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import Button from 'core-components/button'; import Button from 'core-components/button';
import SessionActions from 'actions/session-actions'; import SessionActions from 'actions/session-actions';
@ -24,7 +25,7 @@ class AdminPanelStaffWidget extends React.Component {
</div> </div>
</div> </div>
<div className="admin-panel-staff-widget__profile-pic-wrapper"> <div className="admin-panel-staff-widget__profile-pic-wrapper">
<img className="admin-panel-staff-widget__profile-pic" src={this.props.session.userProfilePic} /> <img className="admin-panel-staff-widget__profile-pic" src={(this.props.session.userProfilePic) ? API.getFileLink(this.props.session.userProfilePic) : (API.getURL() + '/images/logo.png')} />
</div> </div>
</div> </div>
); );

View File

@ -8,6 +8,7 @@
text-align: center; text-align: center;
&__profile-pic-wrapper { &__profile-pic-wrapper {
background-color: white;
position: absolute; position: absolute;
top: 8px; top: 8px;
border: 4px solid $grey; border: 4px solid $grey;

View File

@ -73,7 +73,7 @@ class StaffEditor extends React.Component {
</div> </div>
<label className={this.getPictureWrapperClass()}> <label className={this.getPictureWrapperClass()}>
<div className="staff-editor__card-pic-background"></div> <div className="staff-editor__card-pic-background"></div>
<img className="staff-editor__card-pic" src={this.props.profilePic} /> <img className="staff-editor__card-pic" src={(this.props.profilePic) ? API.getFileLink(this.props.profilePic) : (API.getURL() + '/images/logo.png')} />
{(this.state.loadingPicture) ? <Loading className="staff-editor__card-pic-loading" size="large"/> : <Icon className="staff-editor__card-pic-icon" name="upload" size="4x"/>} {(this.state.loadingPicture) ? <Loading className="staff-editor__card-pic-loading" size="large"/> : <Icon className="staff-editor__card-pic-icon" name="upload" size="4x"/>}
<input className="staff-editor__image-uploader" type="file" multiple={false} accept="image/x-png,image/gif,image/jpeg" onChange={this.onProfilePicChange.bind(this)}/> <input className="staff-editor__image-uploader" type="file" multiple={false} accept="image/x-png,image/gif,image/jpeg" onChange={this.onProfilePicChange.bind(this)}/>
</label> </label>
@ -306,6 +306,7 @@ class StaffEditor extends React.Component {
API.call({ API.call({
path: '/staff/edit', path: '/staff/edit',
dataAsForm: true,
data: { data: {
staffId: this.props.staffId, staffId: this.props.staffId,
file: event.target.files[0] file: event.target.files[0]

View File

@ -2,6 +2,10 @@
.staff-editor { .staff-editor {
&__image-uploader {
opacity: 0;
}
&__card { &__card {
background-color: $primary-red; background-color: $primary-red;
position: relative; position: relative;
@ -11,10 +15,6 @@
border: 2px solid $grey; border: 2px solid $grey;
margin-bottom: 20px; margin-bottom: 20px;
&__image-uploader {
opacity: 0;
}
&-pic { &-pic {
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -45,7 +45,7 @@
&-wrapper { &-wrapper {
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
background-color: $grey; background-color: white;
position: absolute; position: absolute;
top: 20px; top: 20px;
border: 4px solid $grey; border: 4px solid $grey;

View File

@ -119,6 +119,7 @@ class CreateTicketForm extends React.Component {
API.call({ API.call({
path: '/ticket/create', path: '/ticket/create',
dataAsForm: true,
data: _.extend({}, formState, { data: _.extend({}, formState, {
captcha: captcha && captcha.getValue(), captcha: captcha && captcha.getValue(),
departmentId: SessionStore.getDepartments()[formState.departmentIndex].id departmentId: SessionStore.getDepartments()[formState.departmentIndex].id

View File

@ -2,19 +2,35 @@ const _ = require('lodash');
const APIUtils = require('lib-core/APIUtils'); const APIUtils = require('lib-core/APIUtils');
const SessionStore = require('lib-app/session-store'); const SessionStore = require('lib-app/session-store');
const root = 'http://localhost:3000/api'; const url = 'http://localhost:3000';
const apiUrl = 'http://localhost:3000/api';
function processData (data) { function processData (data, dataAsForm = false) {
return _.extend({ let newData;
csrf_token: SessionStore.getSessionData().token,
csrf_userid: SessionStore.getSessionData().userId if(dataAsForm) {
}, data); newData = new FormData();
_.each(data, (value, key) => {
newData.append(key, value);
});
newData.append('csrf_token', SessionStore.getSessionData().token);
newData.append('csrf_userid', SessionStore.getSessionData().userId);
} else {
newData = _.extend({
csrf_token: SessionStore.getSessionData().token,
csrf_userid: SessionStore.getSessionData().userId
}, data)
}
return newData;
} }
module.exports = { module.exports = {
call: function ({path, data, plain}) { call: function ({path, data, plain, dataAsForm}) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
APIUtils.post(root + path, processData(data)) APIUtils.post(apiUrl + path, processData(data, dataAsForm), dataAsForm)
.then(function (result) { .then(function (result) {
console.log(result); console.log(result);
@ -33,5 +49,17 @@ module.exports = {
}); });
}); });
}); });
},
getFileLink(filePath) {
return apiUrl + '/system/download?file=' + filePath;
},
getAPIUrl() {
return apiUrl;
},
getURL() {
return url;
} }
}; };

View File

@ -3,15 +3,25 @@ const $ = require('jquery');
const APIUtils = { const APIUtils = {
getPromise(path, method, data) { getPromise(path, method, data, dataAsForm) {
return (resolve, reject) => { return (resolve, reject) => {
$.ajax({ let options = {
url: path, url: path,
method: method, method: method,
data: data, data: data
processData: false, };
contentType: false
}) if(dataAsForm) {
options = {
url: path,
type: method,
data: data,
processData: false,
contentType: false
};
}
$.ajax(options)
.done(resolve) .done(resolve)
.fail((jqXHR, textStatus) => { .fail((jqXHR, textStatus) => {
reject(textStatus); reject(textStatus);
@ -23,8 +33,8 @@ const APIUtils = {
return new Promise(this.getPromise(path, 'GET')); return new Promise(this.getPromise(path, 'GET'));
}, },
post(path, data) { post(path, data, dataAsForm) {
return new Promise(this.getPromise(path, 'POST', data)); return new Promise(this.getPromise(path, 'POST', data, dataAsForm));
}, },
patch(path, data) { patch(path, data) {

View File

@ -57,8 +57,7 @@ class EditStaffController extends Controller {
$this->staffInstance->sharedDepartmentList = $this->getDepartmentList(); $this->staffInstance->sharedDepartmentList = $this->getDepartmentList();
} }
if(Controller::request('file')) { if($fileUploader = $this->uploadFile()) {
$fileUploader = $this->uploadFile();
$this->staffInstance->profilePic = ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null; $this->staffInstance->profilePic = ($fileUploader instanceof FileUploader) ? $fileUploader->getFileName() : null;
} }

View File

@ -8,7 +8,7 @@ class DownloadController extends Controller {
public function validations() { public function validations() {
return [ return [
'permission' => 'user', 'permission' => 'any',
'requestData' => [ 'requestData' => [
'file' => [ 'file' => [
'validation' => DataValidator::alnum('_.-')->noWhitespace(), 'validation' => DataValidator::alnum('_.-')->noWhitespace(),
@ -20,23 +20,32 @@ class DownloadController extends Controller {
public function handler() { public function handler() {
$fileName = Controller::request('file'); $fileName = Controller::request('file');
$staffUser = Staff::getDataStore($fileName, 'profilePic');
$loggedUser = Controller::getLoggedUser(); if($staffUser->isNull()) {
$ticket = Ticket::getTicket($fileName, 'file'); $loggedUser = Controller::getLoggedUser();
if($ticket->isNull() || ($this->isNotAuthor($ticket, $loggedUser) && $this->isNotOwner($ticket, $loggedUser))) { if($loggedUser->isNull()) {
$ticketEvent = Ticketevent::getDataStore($fileName, 'file');
if($ticketEvent->isNull()) {
print ''; print '';
return; return;
} }
$ticket = $ticketEvent->ticket; $ticket = Ticket::getTicket($fileName, 'file');
if($this->isNotAuthor($ticket, $loggedUser) && $this->isNotOwner($ticket, $loggedUser)) { if($ticket->isNull() || ($this->isNotAuthor($ticket, $loggedUser) && $this->isNotOwner($ticket, $loggedUser))) {
print ''; $ticketEvent = Ticketevent::getDataStore($fileName, 'file');
return;
if($ticketEvent->isNull()) {
print '';
return;
}
$ticket = $ticketEvent->ticket;
if($this->isNotAuthor($ticket, $loggedUser) && $this->isNotOwner($ticket, $loggedUser)) {
print '';
return;
}
} }
} }

View File

@ -116,7 +116,7 @@ class InitSettingsController extends Controller {
'name' => 'Emilia Clarke', 'name' => 'Emilia Clarke',
'email' => 'staff@opensupports.com', 'email' => 'staff@opensupports.com',
'password' => Hashing::hashPassword('staff'), 'password' => Hashing::hashPassword('staff'),
'profilePic' => 'http://www.opensupports.com/profilepic.jpg', 'profilePic' => '',
'level' => 3, 'level' => 3,
'sharedDepartmentList' => Department::getAll(), 'sharedDepartmentList' => Department::getAll(),
'sharedTicketList' => [] 'sharedTicketList' => []

View File

@ -33,10 +33,10 @@ abstract class Controller {
self::$dataRequester = function ($key) { self::$dataRequester = function ($key) {
$app = self::getAppInstance(); $app = self::getAppInstance();
$value = $app->request()->post($key); if (Controller::getAppInstance()->request()->isGet()) {
if(!$value) {
$value = $app->request()->get($key); $value = $app->request()->get($key);
} else {
$value = $app->request()->post($key);
} }
return $value; return $value;
@ -55,9 +55,9 @@ abstract class Controller {
$session = Session::getInstance(); $session = Session::getInstance();
if ($session->isStaffLogged()) { if ($session->isStaffLogged()) {
return Staff::getUser((int)self::request('csrf_userid')); return Staff::getUser($session->getUserId());
} else { } else {
return User::getUser((int)self::request('csrf_userid')); return User::getUser($session->getUserId());
} }
} }

View File

@ -9,8 +9,9 @@ class Response {
); );
$app = \Slim\Slim::getInstance(); $app = \Slim\Slim::getInstance();
$app->response()->setBody(json_encode($response)); $app->response->headers->set('Content-Type', 'application/json');
$app->response()->finalize(); $app->response->setBody(json_encode($response));
$app->response->finalize();
} }
public static function respondSuccess($data = null) { public static function respondSuccess($data = null) {
@ -20,7 +21,8 @@ class Response {
); );
$app = \Slim\Slim::getInstance(); $app = \Slim\Slim::getInstance();
$app->response()->setBody(json_encode($response)); $app->response->headers->set('Content-Type', 'application/json');
$app->response()->finalize(); $app->response->setBody(json_encode($response));
$app->response->finalize();
} }
} }

View File

@ -39,6 +39,10 @@ class Session {
return $this->getStoredData('ticketNumber'); return $this->getStoredData('ticketNumber');
} }
public function getUserId() {
return $this->getStoredData('userId');
}
public function getToken() { public function getToken() {
return $this->getStoredData('token'); return $this->getStoredData('token');
} }