mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-11 13:42:49 +01:00
Merge branch 'release-2.6.9'
Conflicts: app/Http/routes.php app/Ninja/PaymentDrivers/BasePaymentDriver.php composer.lock resources/lang/en/texts.php resources/views/reports/chart_builder.blade.php
This commit is contained in:
commit
c7c253fbd8
@ -1,7 +1,7 @@
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://ninja.dev
|
||||
APP_KEY=SomeRandomString
|
||||
APP_KEY=SomeRandomStringSomeRandomString
|
||||
APP_CIPHER=AES-256-CBC
|
||||
|
||||
DB_TYPE=mysql
|
||||
|
5
.gitattributes
vendored
5
.gitattributes
vendored
@ -1,3 +1,8 @@
|
||||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.less linguist-vendored
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.codeclimate.yml export-ignore
|
||||
.travis.yml export-ignore
|
||||
.styleci.yml export-ignore
|
||||
|
@ -29,6 +29,7 @@ before_install:
|
||||
- if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi;
|
||||
- composer self-update && composer -V
|
||||
# - export USE_ZEND_ALLOC=0
|
||||
- rvm use 1.9.3 --install --fuzzy
|
||||
|
||||
install:
|
||||
# install Composer dependencies
|
||||
|
@ -2,8 +2,15 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
- Auto billing uses credits if they exist
|
||||
|
||||
|
||||
## [2.6.4] - 2016-07-19
|
||||
|
||||
### Added
|
||||
- Added 'Buy Now' buttons
|
||||
|
||||
|
@ -11,7 +11,7 @@ Thanks for your contributions!
|
||||
* Make your changes and commit
|
||||
* Check if your branch is still in sync with the repositorys **`develop`** branch
|
||||
* _Read:_ [Syncing a fork](https://help.github.com/articles/syncing-a-fork/)
|
||||
* _Also read:_ [How to rebase a pull request](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request)
|
||||
* _Also read:_ [How to rebase a pull request](https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request)
|
||||
* Push your branch and create a PR against the Invoice Ninja **`develop`** branch
|
||||
* Update the [Changelog](CHANGELOG.md)
|
||||
|
||||
@ -21,7 +21,7 @@ To make the contribution process nice and easy for anyone, please follow some ru
|
||||
to give a more detailed explanation.
|
||||
* Only one feature/bugfix per issue. If you want to submit more, create multiple issues.
|
||||
* Only one feature/bugfix per PR(pull request). Split more changes into multiple PRs.
|
||||
|
||||
|
||||
#### Coding Style
|
||||
Try to follow the [PSR-2 guidlines](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)
|
||||
|
||||
@ -29,7 +29,7 @@ _Example styling:_
|
||||
```php
|
||||
/**
|
||||
* Gets a preview of the email
|
||||
*
|
||||
*
|
||||
* @param TemplateService $templateService
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
|
30
Gruntfile.js
30
Gruntfile.js
@ -4,12 +4,12 @@ module.exports = function(grunt) {
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
dump_dir: (function() {
|
||||
var out = {};
|
||||
|
||||
|
||||
grunt.file.expand({ filter: 'isDirectory'}, 'public/fonts/invoice-fonts/*').forEach(function(path) {
|
||||
var fontName = /[^/]*$/.exec(path)[0],
|
||||
files = {},
|
||||
license='';
|
||||
|
||||
|
||||
// Add license text
|
||||
grunt.file.expand({ filter: 'isFile'}, path+'/*.txt').forEach(function(path) {
|
||||
var licenseText = grunt.file.read(path);
|
||||
@ -19,10 +19,10 @@ module.exports = function(grunt) {
|
||||
|
||||
license += "/*\n"+licenseText+"\n*/";
|
||||
});
|
||||
|
||||
|
||||
// Create files list
|
||||
files['public/js/vfs_fonts/'+fontName+'.js'] = [path+'/*.ttf'];
|
||||
|
||||
|
||||
out[fontName] = {
|
||||
options: {
|
||||
pre: license+'window.ninjaFontVfs=window.ninjaFontVfs||{};window.ninjaFontVfs.'+fontName+'=',
|
||||
@ -30,8 +30,8 @@ module.exports = function(grunt) {
|
||||
},
|
||||
files: files
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Return the computed object
|
||||
return out;
|
||||
}()),
|
||||
@ -104,8 +104,8 @@ module.exports = function(grunt) {
|
||||
'public/vendor/moment-timezone/builds/moment-timezone-with-data.min.js',
|
||||
'public/vendor/stacktrace-js/dist/stacktrace-with-polyfills.min.js',
|
||||
'public/vendor/fuse.js/src/fuse.min.js',
|
||||
'public/vendor/sweetalert/dist/sweetalert.min.js',
|
||||
//'public/vendor/moment-duration-format/lib/moment-duration-format.js',
|
||||
//'public/vendor/handsontable/dist/jquery.handsontable.full.min.js',
|
||||
//'public/vendor/pdfmake/build/pdfmake.min.js',
|
||||
//'public/vendor/pdfmake/build/vfs_fonts.js',
|
||||
//'public/js/vfs_fonts.js',
|
||||
@ -116,14 +116,12 @@ module.exports = function(grunt) {
|
||||
dest: 'public/built.js',
|
||||
nonull: true
|
||||
},
|
||||
js_public: {
|
||||
/*js_public: {
|
||||
src: [
|
||||
/*
|
||||
'public/js/simpleexpand.js',
|
||||
'public/js/valign.js',
|
||||
'public/js/bootstrap.min.js',
|
||||
'public/js/simpleexpand.js',
|
||||
*/
|
||||
'public/vendor/bootstrap/dist/js/bootstrap.min.js',
|
||||
'public/js/bootstrap-combobox.js',
|
||||
|
||||
@ -142,7 +140,7 @@ module.exports = function(grunt) {
|
||||
'public/vendor/spectrum/spectrum.css',
|
||||
'public/css/bootstrap-combobox.css',
|
||||
'public/css/typeahead.js-bootstrap.css',
|
||||
//'public/vendor/handsontable/dist/jquery.handsontable.full.css',
|
||||
'public/vendor/sweetalert/dist/sweetalert.css',
|
||||
'public/css/style.css',
|
||||
],
|
||||
dest: 'public/css/built.css',
|
||||
@ -150,8 +148,8 @@ module.exports = function(grunt) {
|
||||
options: {
|
||||
process: false
|
||||
}
|
||||
},
|
||||
css_public: {
|
||||
},*/
|
||||
/*css_public: {
|
||||
src: [
|
||||
'public/vendor/bootstrap/dist/css/bootstrap.min.css',
|
||||
'public/vendor/font-awesome/css/font-awesome.min.css',
|
||||
@ -165,8 +163,8 @@ module.exports = function(grunt) {
|
||||
options: {
|
||||
process: false
|
||||
}
|
||||
},
|
||||
js_pdf: {
|
||||
},*/
|
||||
/*js_pdf: {
|
||||
src: [
|
||||
'public/js/pdf_viewer.js',
|
||||
'public/js/compatibility.js',
|
||||
@ -175,7 +173,7 @@ module.exports = function(grunt) {
|
||||
],
|
||||
dest: 'public/pdf.built.js',
|
||||
nonull: true
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
# Invoice Ninja
|
||||
|
||||
[![Build Status](https://travis-ci.org/invoiceninja/invoiceninja.svg?branch=master)](https://travis-ci.org/invoiceninja/invoiceninja)
|
||||
[![Build Status](https://travis-ci.org/invoiceninja/invoiceninja.svg?branch=develop)](https://travis-ci.org/invoiceninja/invoiceninja)
|
||||
[![Join the chat at https://gitter.im/hillelcoren/invoice-ninja](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hillelcoren/invoice-ninja?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## [Hosted](https://www.invoiceninja.com) | [Self-hosted](https://invoiceninja.org)
|
||||
|
75
app/Console/Commands/ResetInvoiceSchemaCounter.php
Normal file
75
app/Console/Commands/ResetInvoiceSchemaCounter.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Invoice;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ResetInvoiceSchemaCounter extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'ninja:reset-invoice-schema-counter
|
||||
{account? : The ID of the account}
|
||||
{--force : Force setting the counter back to "1", regardless if the year changed}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Reset the invoice schema counter at the turn of the year.';
|
||||
|
||||
/**
|
||||
* @var Invoice
|
||||
*/
|
||||
protected $invoice;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$force = $this->option('force');
|
||||
$account = $this->argument('account');
|
||||
|
||||
$accounts = null;
|
||||
|
||||
if ($account) {
|
||||
$accounts = Account::find($account)->get();
|
||||
} else {
|
||||
$accounts = Account::all();
|
||||
}
|
||||
|
||||
$latestInvoice = $this->invoice->latest()->first();
|
||||
$invoiceYear = Carbon::parse($latestInvoice->created_at)->year;
|
||||
|
||||
if(Carbon::now()->year > $invoiceYear || $force) {
|
||||
$accounts->transform(function ($a) {
|
||||
/** @var Account $a */
|
||||
$a->invoice_number_counter = 1;
|
||||
$a->update();
|
||||
});
|
||||
|
||||
$this->info('The counter has been resetted successfully for '.$accounts->count().' account(s).');
|
||||
}
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@ class Kernel extends ConsoleKernel
|
||||
'App\Console\Commands\SendRenewalInvoices',
|
||||
'App\Console\Commands\ChargeRenewalInvoices',
|
||||
'App\Console\Commands\SendReminders',
|
||||
'App\Console\Commands\TestOFX',
|
||||
'App\Console\Commands\GenerateResources',
|
||||
'App\Console\Commands\TestOFX',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -1461,6 +1461,7 @@ class AccountController extends BaseController
|
||||
return trans('texts.create_invoice_for_sample');
|
||||
}
|
||||
|
||||
/** @var \App\Models\Account $account */
|
||||
$account = Auth::user()->account;
|
||||
$invitation = $invoice->invitations->first();
|
||||
|
||||
|
@ -60,6 +60,8 @@ class AccountGatewayController extends BaseController
|
||||
$data['hiddenFields'] = Gateway::$hiddenFields;
|
||||
$data['selectGateways'] = Gateway::where('id', '=', $accountGateway->gateway_id)->get();
|
||||
|
||||
$this->testGateway($accountGateway);
|
||||
|
||||
return View::make('accounts.account_gateway', $data);
|
||||
}
|
||||
|
||||
@ -307,7 +309,7 @@ class AccountGatewayController extends BaseController
|
||||
$account->account_gateways()->save($accountGateway);
|
||||
}
|
||||
|
||||
if(isset($wepayResponse)) {
|
||||
if (isset($wepayResponse)) {
|
||||
return $wepayResponse;
|
||||
} else {
|
||||
if ($accountGatewayPublicId) {
|
||||
@ -322,6 +324,16 @@ class AccountGatewayController extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
private function testGateway($accountGateway)
|
||||
{
|
||||
$paymentDriver = $accountGateway->paymentDriver();
|
||||
$result = $paymentDriver->isValid();
|
||||
|
||||
if ($result !== true) {
|
||||
Session::flash('error', $result . ' - ' . trans('texts.gateway_config_error'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function getWePayUpdateUri($accountGateway)
|
||||
{
|
||||
if ($accountGateway->gateway_id != GATEWAY_WEPAY) {
|
||||
|
323
app/Http/Controllers/BotController.php
Normal file
323
app/Http/Controllers/BotController.php
Normal file
@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use DB;
|
||||
use Utils;
|
||||
use Cache;
|
||||
use Input;
|
||||
use Exception;
|
||||
use App\Libraries\Skype\SkypeResponse;
|
||||
use App\Libraries\CurlUtils;
|
||||
use App\Models\User;
|
||||
use App\Models\SecurityCode;
|
||||
use App\Ninja\Intents\BaseIntent;
|
||||
use App\Ninja\Mailers\UserMailer;
|
||||
|
||||
class BotController extends Controller
|
||||
{
|
||||
protected $userMailer;
|
||||
|
||||
public function __construct(UserMailer $userMailer)
|
||||
{
|
||||
$this->userMailer = $userMailer;
|
||||
}
|
||||
|
||||
public function handleMessage($platform)
|
||||
{
|
||||
$input = Input::all();
|
||||
$botUserId = $input['from']['id'];
|
||||
|
||||
if ( ! $token = $this->authenticate($input)) {
|
||||
return SkypeResponse::message(trans('texts.not_authorized'));
|
||||
}
|
||||
|
||||
try {
|
||||
if ($input['type'] === 'contactRelationUpdate') {
|
||||
// brand new user, ask for their email
|
||||
if ($input['action'] === 'add') {
|
||||
$response = SkypeResponse::message(trans('texts.bot_get_email'));
|
||||
$state = BOT_STATE_GET_EMAIL;
|
||||
} elseif ($input['action'] === 'remove') {
|
||||
$this->removeBot($botUserId);
|
||||
$this->saveState($token, false);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
$state = $this->loadState($token);
|
||||
$text = strip_tags($input['text']);
|
||||
|
||||
// user gaves us their email
|
||||
if ($state === BOT_STATE_GET_EMAIL) {
|
||||
if ($this->validateEmail($text, $botUserId)) {
|
||||
$response = SkypeResponse::message(trans('texts.bot_get_code'));
|
||||
$state = BOT_STATE_GET_CODE;
|
||||
} else {
|
||||
$response = SkypeResponse::message(trans('texts.email_not_found', ['email' => $text]));
|
||||
}
|
||||
// user sent the scurity code
|
||||
} elseif ($state === BOT_STATE_GET_CODE) {
|
||||
if ($this->validateCode($text, $botUserId)) {
|
||||
$response = SkypeResponse::message(trans('texts.bot_welcome') . trans('texts.bot_help_message'));
|
||||
$state = BOT_STATE_READY;
|
||||
} else {
|
||||
$response = SkypeResponse::message(trans('texts.invalid_code'));
|
||||
}
|
||||
// regular chat message
|
||||
} else {
|
||||
if ($message === 'help') {
|
||||
$response = SkypeResponse::message(trans('texts.bot_help_message'));
|
||||
} elseif ($message == 'status') {
|
||||
$response = SkypeResponse::message(trans('texts.intent_not_supported'));
|
||||
} else {
|
||||
if ( ! $user = User::whereBotUserId($botUserId)->with('account')->first()) {
|
||||
return SkypeResponse::message(trans('texts.not_authorized'));
|
||||
}
|
||||
|
||||
Auth::onceUsingId($user->id);
|
||||
$user->account->loadLocalizationSettings();
|
||||
|
||||
$data = $this->parseMessage($text);
|
||||
$intent = BaseIntent::createIntent($state, $data);
|
||||
$response = $intent->process();
|
||||
$state = $intent->getState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->saveState($token, $state);
|
||||
} catch (Exception $exception) {
|
||||
$response = SkypeResponse::message($exception->getMessage());
|
||||
}
|
||||
|
||||
$this->sendResponse($token, $botUserId, $response);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
private function authenticate($input)
|
||||
{
|
||||
$headers = getallheaders();
|
||||
$token = isset($headers['Authorization']) ? $headers['Authorization'] : false;
|
||||
|
||||
if (Utils::isNinjaDev()) {
|
||||
// skip validation for testing
|
||||
} elseif ( ! $this->validateToken($token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($token = Cache::get('msbot_token')) {
|
||||
return $token;
|
||||
}
|
||||
|
||||
$clientId = env('MSBOT_CLIENT_ID');
|
||||
$clientSecret = env('MSBOT_CLIENT_SECRET');
|
||||
$scope = 'https://graph.microsoft.com/.default';
|
||||
|
||||
$data = sprintf('grant_type=client_credentials&client_id=%s&client_secret=%s&scope=%s', $clientId, $clientSecret, $scope);
|
||||
|
||||
$response = CurlUtils::post(MSBOT_LOGIN_URL, $data);
|
||||
$response = json_decode($response);
|
||||
|
||||
$expires = ($response->expires_in / 60) - 5;
|
||||
Cache::put('msbot_token', $response->access_token, $expires);
|
||||
|
||||
return $response->access_token;
|
||||
}
|
||||
|
||||
private function loadState($token)
|
||||
{
|
||||
$url = sprintf('%s/botstate/skype/conversations/%s', MSBOT_STATE_URL, '29:1C-OsU7OWBEDOYJhQUsDkYHmycOwOq9QOg5FVTwRX9ts');
|
||||
|
||||
$headers = [
|
||||
'Authorization: Bearer ' . $token
|
||||
];
|
||||
|
||||
$response = CurlUtils::get($url, $headers);
|
||||
$data = json_decode($response);
|
||||
|
||||
return json_decode($data->data);
|
||||
}
|
||||
|
||||
private function parseMessage($message)
|
||||
{
|
||||
$appId = env('MSBOT_LUIS_APP_ID');
|
||||
$subKey = env('MSBOT_LUIS_SUBSCRIPTION_KEY');
|
||||
$message = rawurlencode($message);
|
||||
|
||||
$url = sprintf('%s?id=%s&subscription-key=%s&q=%s', MSBOT_LUIS_URL, $appId, $subKey, $message);
|
||||
$data = file_get_contents($url);
|
||||
$data = json_decode($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function saveState($token, $data)
|
||||
{
|
||||
$url = sprintf('%s/botstate/skype/conversations/%s', MSBOT_STATE_URL, '29:1C-OsU7OWBEDOYJhQUsDkYHmycOwOq9QOg5FVTwRX9ts');
|
||||
|
||||
$headers = [
|
||||
'Authorization: Bearer ' . $token,
|
||||
'Content-Type: application/json',
|
||||
];
|
||||
|
||||
//echo "STATE<pre>" . htmlentities(json_encode($data), JSON_PRETTY_PRINT) . "</pre>";
|
||||
|
||||
$data = '{ eTag: "*", data: "' . addslashes(json_encode($data)) . '" }';
|
||||
|
||||
|
||||
CurlUtils::post($url, $data, $headers);
|
||||
}
|
||||
|
||||
private function sendResponse($token, $to, $message)
|
||||
{
|
||||
$url = sprintf('%s/conversations/%s/activities/', SKYPE_API_URL, $to);
|
||||
|
||||
$headers = [
|
||||
'Authorization: Bearer ' . $token,
|
||||
];
|
||||
|
||||
//echo "<pre>" . htmlentities(json_encode(json_decode($message), JSON_PRETTY_PRINT)) . "</pre>";
|
||||
|
||||
$response = CurlUtils::post($url, $message, $headers);
|
||||
|
||||
//var_dump($response);
|
||||
}
|
||||
|
||||
private function validateEmail($email, $botUserId)
|
||||
{
|
||||
if ( ! $email || ! $botUserId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// delete any expired codes
|
||||
SecurityCode::whereBotUserId($botUserId)
|
||||
->where('created_at', '<', DB::raw('now() - INTERVAL 10 MINUTE'))
|
||||
->delete();
|
||||
|
||||
if (SecurityCode::whereBotUserId($botUserId)->first()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = User::whereEmail($email)
|
||||
->whereNull('bot_user_id')
|
||||
->first();
|
||||
|
||||
if ( ! $user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = new SecurityCode();
|
||||
$code->user_id = $user->id;
|
||||
$code->account_id = $user->account_id;
|
||||
$code->code = mt_rand(100000, 999999);
|
||||
$code->bot_user_id = $botUserId;
|
||||
$code->save();
|
||||
|
||||
$this->userMailer->sendSecurityCode($user, $code->code);
|
||||
|
||||
return $code->code;
|
||||
}
|
||||
|
||||
private function validateCode($input, $botUserId)
|
||||
{
|
||||
if ( ! $input || ! $botUserId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$code = SecurityCode::whereBotUserId($botUserId)
|
||||
->where('created_at', '>', DB::raw('now() - INTERVAL 10 MINUTE'))
|
||||
->where('attempts', '<', 5)
|
||||
->first();
|
||||
|
||||
if ( ! $code) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! hash_equals($code->code, $input)) {
|
||||
$code->attempts += 1;
|
||||
$code->save();
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = User::find($code->user_id);
|
||||
$user->bot_user_id = $code->bot_user_id;
|
||||
$user->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function removeBot($botUserId)
|
||||
{
|
||||
$user = User::whereBotUserId($botUserId)->first();
|
||||
$user->bot_user_id = null;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
private function validateToken($token)
|
||||
{
|
||||
if ( ! $token) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://blogs.msdn.microsoft.com/tsmatsuz/2016/07/12/developing-skype-bot/
|
||||
// 0:Invalid, 1:Valid
|
||||
$token_valid = 0;
|
||||
|
||||
// 1 separate token by dot (.)
|
||||
$token_arr = explode('.', $token);
|
||||
$headers_enc = $token_arr[0];
|
||||
$claims_enc = $token_arr[1];
|
||||
$sig_enc = $token_arr[2];
|
||||
|
||||
// 2 base 64 url decoding
|
||||
$headers_arr = json_decode($this->base64_url_decode($headers_enc), TRUE);
|
||||
$claims_arr = json_decode($this->base64_url_decode($claims_enc), TRUE);
|
||||
$sig = $this->base64_url_decode($sig_enc);
|
||||
|
||||
// 3 get key list
|
||||
$keylist = file_get_contents('https://api.aps.skype.com/v1/keys');
|
||||
$keylist_arr = json_decode($keylist, TRUE);
|
||||
foreach($keylist_arr['keys'] as $key => $value) {
|
||||
|
||||
// 4 select one key (which matches)
|
||||
if($value['kid'] == $headers_arr['kid']) {
|
||||
|
||||
// 5 get public key from key info
|
||||
$cert_txt = '-----BEGIN CERTIFICATE-----' . "\n" . chunk_split($value['x5c'][0], 64) . '-----END CERTIFICATE-----';
|
||||
$cert_obj = openssl_x509_read($cert_txt);
|
||||
$pkey_obj = openssl_pkey_get_public($cert_obj);
|
||||
$pkey_arr = openssl_pkey_get_details($pkey_obj);
|
||||
$pkey_txt = $pkey_arr['key'];
|
||||
|
||||
// 6 verify signature
|
||||
$token_valid = openssl_verify($headers_enc . '.' . $claims_enc, $sig, $pkey_txt, OPENSSL_ALGO_SHA256);
|
||||
}
|
||||
}
|
||||
|
||||
// 7 show result
|
||||
return ($token_valid == 1);
|
||||
}
|
||||
|
||||
private function base64_url_decode($arg) {
|
||||
$res = $arg;
|
||||
$res = str_replace('-', '+', $res);
|
||||
$res = str_replace('_', '/', $res);
|
||||
switch (strlen($res) % 4) {
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
$res .= "==";
|
||||
break;
|
||||
case 3:
|
||||
$res .= "=";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
$res = base64_decode($res);
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
@ -62,7 +62,7 @@ class CreditController extends BaseController
|
||||
'method' => 'POST',
|
||||
'url' => 'credits',
|
||||
'title' => trans('texts.new_credit'),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||
];
|
||||
|
||||
return View::make('credits.edit', $data);
|
||||
|
@ -52,7 +52,10 @@ class DocumentAPIController extends BaseAPIController
|
||||
{
|
||||
$document = $request->entity();
|
||||
|
||||
return DocumentController::getDownloadResponse($document);
|
||||
if(array_key_exists($document->type, Document::$types))
|
||||
return DocumentController::getDownloadResponse($document);
|
||||
else
|
||||
return $this->errorResponse(['error'=>'Invalid mime type'],400);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -611,4 +611,15 @@ class InvoiceController extends BaseController
|
||||
|
||||
return View::make('invoices.history', $data);
|
||||
}
|
||||
|
||||
public function checkInvoiceNumber($invoiceNumber)
|
||||
{
|
||||
$count = Invoice::scope()
|
||||
->whereInvoiceNumber($invoiceNumber)
|
||||
->withTrashed()
|
||||
->count();
|
||||
|
||||
return $count ? RESULT_FAILURE : RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -130,8 +130,9 @@ class OnlinePaymentController extends BaseController
|
||||
}
|
||||
|
||||
try {
|
||||
$paymentDriver->completeOffsitePurchase(Input::all());
|
||||
Session::flash('message', trans('texts.applied_payment'));
|
||||
if ($paymentDriver->completeOffsitePurchase(Input::all())) {
|
||||
Session::flash('message', trans('texts.applied_payment'));
|
||||
}
|
||||
return redirect()->to('view/' . $invitation->invitation_key);
|
||||
} catch (Exception $exception) {
|
||||
return $this->error($paymentDriver, $exception);
|
||||
|
@ -25,6 +25,10 @@ class CreateInvoiceAPIRequest extends InvoiceRequest
|
||||
'invoice_items' => 'valid_invoice_items',
|
||||
'invoice_number' => 'unique:invoices,invoice_number,,id,account_id,' . $this->user()->account_id,
|
||||
'discount' => 'positive',
|
||||
'invoice_date' => 'date',
|
||||
'due_date' => 'date',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
@ -24,6 +24,10 @@ class CreateInvoiceRequest extends InvoiceRequest
|
||||
'invoice_items' => 'valid_invoice_items',
|
||||
'invoice_number' => 'required|unique:invoices,invoice_number,,id,account_id,' . $this->user()->account_id,
|
||||
'discount' => 'positive',
|
||||
'invoice_date' => 'date',
|
||||
'due_date' => 'date',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
/* There's a problem parsing the dates
|
||||
|
@ -44,6 +44,11 @@ class EntityRequest extends Request {
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
public function setEntity($entity)
|
||||
{
|
||||
$this->entity = $entity;
|
||||
}
|
||||
|
||||
public function authorize()
|
||||
{
|
||||
if ($this->entity()) {
|
||||
|
@ -29,6 +29,10 @@ class UpdateInvoiceAPIRequest extends InvoiceRequest
|
||||
'invoice_items' => 'valid_invoice_items',
|
||||
'invoice_number' => 'unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
|
||||
'discount' => 'positive',
|
||||
'invoice_date' => 'date',
|
||||
'due_date' => 'date',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
return $rules;
|
||||
|
@ -20,12 +20,16 @@ class UpdateInvoiceRequest extends InvoiceRequest
|
||||
public function rules()
|
||||
{
|
||||
$invoiceId = $this->entity()->id;
|
||||
|
||||
|
||||
$rules = [
|
||||
'client.contacts' => 'valid_contacts',
|
||||
'invoice_items' => 'valid_invoice_items',
|
||||
'invoice_number' => 'required|unique:invoices,invoice_number,' . $invoiceId . ',id,account_id,' . $this->user()->account_id,
|
||||
'discount' => 'positive',
|
||||
'invoice_date' => 'date',
|
||||
'due_date' => 'date',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
];
|
||||
|
||||
/* There's a problem parsing the dates
|
||||
|
37
app/Http/ViewComposers/AppLanguageComposer.php
Normal file
37
app/Http/ViewComposers/AppLanguageComposer.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\ViewComposers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AppLanguageComposer
|
||||
{
|
||||
/**
|
||||
* Bind data to the view.
|
||||
*
|
||||
* @param View $view
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function compose(View $view)
|
||||
{
|
||||
$view->with('appLanguage', $this->getLanguage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the language from the current locale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getLanguage()
|
||||
{
|
||||
$code = app()->getLocale();
|
||||
|
||||
if(preg_match('/_/', $code)) {
|
||||
$codes = explode('_', $code);
|
||||
$code = $codes[0];
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
}
|
@ -85,6 +85,7 @@ Route::match(['GET', 'POST'], '/buy_now/{gateway_type?}', 'OnlinePaymentControll
|
||||
|
||||
Route::post('/hook/email_bounced', 'AppController@emailBounced');
|
||||
Route::post('/hook/email_opened', 'AppController@emailOpened');
|
||||
Route::post('/hook/bot/{platform?}', 'BotController@handleMessage');
|
||||
Route::post('/payment_hook/{accountKey}/{gatewayId}', 'OnlinePaymentController@handlePaymentWebhook');
|
||||
|
||||
// Laravel auth routes
|
||||
@ -125,7 +126,8 @@ Route::group(['middleware' => 'auth:user'], function() {
|
||||
Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible');
|
||||
Route::get('hide_message', 'HomeController@hideMessage');
|
||||
Route::get('force_inline_pdf', 'UserController@forcePDFJS');
|
||||
Route::get('account/getSearchData', ['as' => 'getSearchData', 'uses' => 'AccountController@getSearchData']);
|
||||
Route::get('account/get_search_data', ['as' => 'get_search_data', 'uses' => 'AccountController@getSearchData']);
|
||||
Route::get('check_invoice_number/{invoice_number}', 'InvoiceController@checkInvoiceNumber');
|
||||
|
||||
Route::get('settings/user_details', 'AccountController@showUserDetails');
|
||||
Route::post('settings/user_details', 'AccountController@saveUserDetails');
|
||||
@ -351,7 +353,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('ENTITY_CONTACT', 'contact');
|
||||
define('ENTITY_INVOICE', 'invoice');
|
||||
define('ENTITY_DOCUMENT', 'document');
|
||||
define('ENTITY_INVOICE_ITEMS', 'invoice_items');
|
||||
define('ENTITY_INVOICE_ITEM', 'invoice_item');
|
||||
define('ENTITY_INVITATION', 'invitation');
|
||||
define('ENTITY_RECURRING_INVOICE', 'recurring_invoice');
|
||||
define('ENTITY_PAYMENT', 'payment');
|
||||
@ -608,7 +610,7 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('NINJA_WEB_URL', env('NINJA_WEB_URL', 'https://www.invoiceninja.com'));
|
||||
define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
|
||||
define('NINJA_DATE', '2000-01-01');
|
||||
define('NINJA_VERSION', '2.6.8' . env('NINJA_VERSION_SUFFIX'));
|
||||
define('NINJA_VERSION', '2.6.9' . env('NINJA_VERSION_SUFFIX'));
|
||||
|
||||
define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'));
|
||||
define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
|
||||
@ -626,6 +628,11 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'));
|
||||
define('GOOGLE_ANALYITCS_URL', env('GOOGLE_ANALYITCS_URL', 'https://www.google-analytics.com/collect'));
|
||||
|
||||
define('MSBOT_LOGIN_URL', 'https://login.microsoftonline.com/common/oauth2/v2.0/token');
|
||||
define('MSBOT_LUIS_URL', 'https://api.projectoxford.ai/luis/v1/application');
|
||||
define('SKYPE_API_URL', 'https://apis.skype.com/v3');
|
||||
define('MSBOT_STATE_URL', 'https://state.botframework.com/v3');
|
||||
|
||||
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
|
||||
|
||||
define('COUNT_FREE_DESIGNS', 4);
|
||||
@ -790,6 +797,25 @@ if (!defined('CONTACT_EMAIL')) {
|
||||
define('WEPAY_APP_FEE_MULTIPLIER', env('WEPAY_APP_FEE_MULTIPLIER', 0.002));
|
||||
define('WEPAY_APP_FEE_FIXED', env('WEPAY_APP_FEE_MULTIPLIER', 0.00));
|
||||
|
||||
define('SKYPE_CARD_RECEIPT', 'message/card.receipt');
|
||||
define('SKYPE_CARD_CAROUSEL', 'message/card.carousel');
|
||||
define('SKYPE_CARD_HERO', '');
|
||||
|
||||
define('BOT_STATE_GET_EMAIL', 'get_email');
|
||||
define('BOT_STATE_GET_CODE', 'get_code');
|
||||
define('BOT_STATE_READY', 'ready');
|
||||
define('SIMILAR_MIN_THRESHOLD', 50);
|
||||
|
||||
// https://docs.botframework.com/en-us/csharp/builder/sdkreference/attachments.html
|
||||
define('SKYPE_BUTTON_OPEN_URL', 'openUrl');
|
||||
define('SKYPE_BUTTON_IM_BACK', 'imBack');
|
||||
define('SKYPE_BUTTON_POST_BACK', 'postBack');
|
||||
define('SKYPE_BUTTON_CALL', 'call'); // "tel:123123123123"
|
||||
define('SKYPE_BUTTON_PLAY_AUDIO', 'playAudio');
|
||||
define('SKYPE_BUTTON_PLAY_VIDEO', 'playVideo');
|
||||
define('SKYPE_BUTTON_SHOW_IMAGE', 'showImage');
|
||||
define('SKYPE_BUTTON_DOWNLOAD_FILE', 'downloadFile');
|
||||
|
||||
$creditCards = [
|
||||
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
|
||||
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],
|
||||
|
36
app/Libraries/CurlUtils.php
Normal file
36
app/Libraries/CurlUtils.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php namespace App\Libraries;
|
||||
|
||||
class CurlUtils
|
||||
{
|
||||
public static function post($url, $data, $headers = false)
|
||||
{
|
||||
return self::exec('POST', $url, $data, $headers);
|
||||
}
|
||||
|
||||
public static function get($url, $headers = false)
|
||||
{
|
||||
return self::exec('GET', $url, null, $headers);
|
||||
}
|
||||
|
||||
public static function exec($method, $url, $data, $headers = false)
|
||||
{
|
||||
$curl = curl_init();
|
||||
|
||||
$opts = [
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => $method,
|
||||
CURLOPT_HTTPHEADER => $headers ?: [],
|
||||
];
|
||||
|
||||
if ($data) {
|
||||
$opts[CURLOPT_POSTFIELDS] = $data;
|
||||
}
|
||||
|
||||
curl_setopt_array($curl, $opts);
|
||||
$response = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
12
app/Libraries/Skype/ButtonCard.php
Normal file
12
app/Libraries/Skype/ButtonCard.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
class ButtonCard
|
||||
{
|
||||
public function __construct($type, $title, $value, $url = false)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->title = $title;
|
||||
$this->value = $value;
|
||||
$this->image = $url;
|
||||
}
|
||||
}
|
15
app/Libraries/Skype/CarouselCard.php
Normal file
15
app/Libraries/Skype/CarouselCard.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
class CarouselCard
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->contentType = 'application/vnd.microsoft.card.carousel';
|
||||
$this->attachments = [];
|
||||
}
|
||||
|
||||
public function addAttachment($attachment)
|
||||
{
|
||||
$this->attachments[] = $attachment;
|
||||
}
|
||||
}
|
33
app/Libraries/Skype/HeroCard.php
Normal file
33
app/Libraries/Skype/HeroCard.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class HeroCard
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->contentType = 'application/vnd.microsoft.card.hero';
|
||||
$this->content = new stdClass;
|
||||
$this->content->buttons = [];
|
||||
}
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->content->title = $title;
|
||||
}
|
||||
|
||||
public function setSubitle($subtitle)
|
||||
{
|
||||
$this->content->subtitle = $subtitle;
|
||||
}
|
||||
|
||||
public function setText($text)
|
||||
{
|
||||
$this->content->text = $text;
|
||||
}
|
||||
|
||||
public function addButton($type, $title, $value, $url = false)
|
||||
{
|
||||
$this->content->buttons[] = new ButtonCard($type, $title, $value, $url);
|
||||
}
|
||||
}
|
79
app/Libraries/Skype/InvoiceCard.php
Normal file
79
app/Libraries/Skype/InvoiceCard.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
use HTML;
|
||||
use stdClass;
|
||||
|
||||
class InvoiceCard
|
||||
{
|
||||
public function __construct($invoice)
|
||||
{
|
||||
$this->contentType = 'application/vnd.microsoft.card.receipt';
|
||||
$this->content = new stdClass;
|
||||
$this->content->facts = [];
|
||||
$this->content->items = [];
|
||||
$this->content->buttons = [];
|
||||
|
||||
$this->setTitle('test');
|
||||
|
||||
$this->setTitle(trans('texts.invoice_for_client', [
|
||||
'invoice' => link_to($invoice->getRoute(), $invoice->invoice_number),
|
||||
'client' => link_to($invoice->client->getRoute(), $invoice->client->getDisplayName())
|
||||
]));
|
||||
|
||||
$this->addFact(trans('texts.email'), HTML::mailto($invoice->client->contacts[0]->email)->toHtml());
|
||||
|
||||
if ($invoice->due_date) {
|
||||
$this->addFact($invoice->present()->dueDateLabel, $invoice->present()->due_date);
|
||||
}
|
||||
|
||||
if ($invoice->po_number) {
|
||||
$this->addFact(trans('texts.po_number'), $invoice->po_number);
|
||||
}
|
||||
|
||||
if ($invoice->discount) {
|
||||
$this->addFact(trans('texts.discount'), $invoice->present()->discount);
|
||||
}
|
||||
|
||||
foreach ($invoice->invoice_items as $item) {
|
||||
$this->addItem($item, $invoice->account);
|
||||
}
|
||||
|
||||
$this->setTotal($invoice->present()->requestedAmount);
|
||||
|
||||
if (floatval($invoice->amount)) {
|
||||
$this->addButton(SKYPE_BUTTON_OPEN_URL, trans('texts.download_pdf'), $invoice->getInvitationLink('view', true));
|
||||
$this->addButton(SKYPE_BUTTON_IM_BACK, trans('texts.email_invoice'), trans('texts.email_invoice'));
|
||||
} else {
|
||||
$this->addButton(SKYPE_BUTTON_IM_BACK, trans('texts.list_products'), trans('texts.list_products'));
|
||||
}
|
||||
}
|
||||
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->content->title = $title;
|
||||
}
|
||||
|
||||
public function setTotal($value)
|
||||
{
|
||||
$this->content->total = $value;
|
||||
}
|
||||
|
||||
public function addFact($key, $value)
|
||||
{
|
||||
$fact = new stdClass;
|
||||
$fact->key = $key;
|
||||
$fact->value = $value;
|
||||
|
||||
$this->content->facts[] = $fact;
|
||||
}
|
||||
|
||||
public function addItem($item, $account)
|
||||
{
|
||||
$this->content->items[] = new InvoiceItemCard($item, $account);
|
||||
}
|
||||
|
||||
public function addButton($type, $title, $value, $url = false)
|
||||
{
|
||||
$this->content->buttons[] = new ButtonCard($type, $title, $value, $url);
|
||||
}
|
||||
}
|
12
app/Libraries/Skype/InvoiceItemCard.php
Normal file
12
app/Libraries/Skype/InvoiceItemCard.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
class InvoiceItemCard
|
||||
{
|
||||
public function __construct($invoiceItem, $account)
|
||||
{
|
||||
$this->title = intval($invoiceItem->qty) . ' ' . $invoiceItem->product_key;
|
||||
$this->subtitle = $invoiceItem->notes;
|
||||
$this->quantity = $invoiceItem->qty;
|
||||
$this->price = $account->formatMoney($invoiceItem->cost);
|
||||
}
|
||||
}
|
28
app/Libraries/Skype/SkypeResponse.php
Normal file
28
app/Libraries/Skype/SkypeResponse.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php namespace App\Libraries\Skype;
|
||||
|
||||
class SkypeResponse
|
||||
{
|
||||
public function __construct($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->attachments = [];
|
||||
}
|
||||
|
||||
public static function message($message)
|
||||
{
|
||||
$instance = new self('message/text');
|
||||
$instance->setText($message);
|
||||
|
||||
return json_encode($instance);
|
||||
}
|
||||
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public function addAttachment($attachment)
|
||||
{
|
||||
$this->attachments[] = $attachment;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
use Auth;
|
||||
use Eloquent;
|
||||
use Utils;
|
||||
use Validator;
|
||||
|
||||
/**
|
||||
* Class EntityModel
|
||||
@ -86,6 +87,11 @@ class EntityModel extends Eloquent
|
||||
return '[' . $this->getEntityType().':'.$this->public_id.':'.$this->getDisplayName() . ']';
|
||||
}
|
||||
|
||||
public function entityKey()
|
||||
{
|
||||
return $this->public_id . ':' . $this->getEntityType();
|
||||
}
|
||||
|
||||
/*
|
||||
public function getEntityType()
|
||||
{
|
||||
@ -190,4 +196,37 @@ class EntityModel extends Eloquent
|
||||
$name = $parts[count($parts)-1];
|
||||
return strtolower($name) . '_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $entityType
|
||||
* @return bool|string
|
||||
*/
|
||||
public static function validate($data, $entityType, $entity = false)
|
||||
{
|
||||
// Use the API request if it exists
|
||||
$action = $entity ? 'update' : 'create';
|
||||
$requestClass = sprintf('App\\Http\\Requests\\%s%sAPIRequest', ucwords($action), ucwords($entityType));
|
||||
if ( ! class_exists($requestClass)) {
|
||||
$requestClass = sprintf('App\\Http\\Requests\\%s%sRequest', ucwords($action), ucwords($entityType));
|
||||
}
|
||||
|
||||
$request = new $requestClass();
|
||||
$request->setUserResolver(function() { return Auth::user(); });
|
||||
$request->setEntity($entity);
|
||||
$request->replace($data);
|
||||
|
||||
if ( ! $request->authorize()) {
|
||||
return trans('texts.not_allowed');
|
||||
}
|
||||
|
||||
$validator = Validator::make($data, $request->rules());
|
||||
|
||||
if ($validator->fails()) {
|
||||
return $validator->messages()->first();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -516,6 +516,15 @@ class Invoice extends EntityModel implements BalanceAffecting
|
||||
return self::calcLink($this);
|
||||
}
|
||||
|
||||
public function getInvitationLink($type = 'view', $forceOnsite = false)
|
||||
{
|
||||
if ( ! $this->relationLoaded('invitations')) {
|
||||
$this->load('invitations');
|
||||
}
|
||||
|
||||
return $this->invitations[0]->getLink($type, $forceOnsite);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -7,6 +7,14 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
*/
|
||||
class InvoiceItem extends EntityModel
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getEntityType()
|
||||
{
|
||||
return ENTITY_INVOICE_ITEM;
|
||||
}
|
||||
|
||||
use SoftDeletes;
|
||||
/**
|
||||
* @var array
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Laracasts\Presenter\PresentableTrait;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
@ -7,12 +8,18 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
*/
|
||||
class Product extends EntityModel
|
||||
{
|
||||
use PresentableTrait;
|
||||
use SoftDeletes;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $presenter = 'App\Ninja\Presenters\ProductPresenter';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
|
15
app/Models/SecurityCode.php
Normal file
15
app/Models/SecurityCode.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php namespace App\Models;
|
||||
|
||||
use Eloquent;
|
||||
|
||||
/**
|
||||
* Class DatetimeFormat
|
||||
*/
|
||||
class SecurityCode extends Eloquent
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $timestamps = false;
|
||||
|
||||
}
|
227
app/Ninja/Intents/BaseIntent.php
Normal file
227
app/Ninja/Intents/BaseIntent.php
Normal file
@ -0,0 +1,227 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use stdClass;
|
||||
use Exception;
|
||||
use App\Libraries\CurlUtils;
|
||||
use App\Libraries\Skype\SkypeResponse;
|
||||
|
||||
class BaseIntent
|
||||
{
|
||||
protected $state;
|
||||
protected $parameters;
|
||||
protected $fieldMap = [];
|
||||
|
||||
public function __construct($state, $data)
|
||||
{
|
||||
//if (true) {
|
||||
if ( ! $state || is_string($state)) {
|
||||
$state = new stdClass;
|
||||
foreach (['current', 'previous'] as $reference) {
|
||||
$state->$reference = new stdClass;
|
||||
$state->$reference->entityType = false;
|
||||
foreach ([ENTITY_INVOICE, ENTITY_CLIENT, ENTITY_INVOICE_ITEM] as $entityType) {
|
||||
$state->$reference->$entityType = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->state = $state;
|
||||
$this->data = $data;
|
||||
|
||||
//var_dump($state);
|
||||
}
|
||||
|
||||
public static function createIntent($state, $data)
|
||||
{
|
||||
if ( ! count($data->intents)) {
|
||||
throw new Exception(trans('texts.intent_not_found'));
|
||||
}
|
||||
|
||||
$intent = $data->intents[0]->intent;
|
||||
$entityType = false;
|
||||
|
||||
foreach ($data->entities as $entity) {
|
||||
if ($entity->type === 'EntityType') {
|
||||
$entityType = $entity->entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $entityType) {
|
||||
$entityType = $state->current->entityType;
|
||||
}
|
||||
|
||||
$entityType = ucwords(strtolower($entityType));
|
||||
$intent = str_replace('Entity', $entityType, $intent);
|
||||
$className = "App\\Ninja\\Intents\\{$intent}Intent";
|
||||
|
||||
//echo "Intent: $intent<p>";
|
||||
|
||||
if ( ! class_exists($className)) {
|
||||
throw new Exception(trans('texts.intent_not_supported'));
|
||||
}
|
||||
|
||||
return (new $className($state, $data));
|
||||
}
|
||||
|
||||
|
||||
public function process()
|
||||
{
|
||||
// do nothing by default
|
||||
}
|
||||
|
||||
public function setStateEntities($entityType, $entities)
|
||||
{
|
||||
if ( ! is_array($entities)) {
|
||||
$entities = [$entities];
|
||||
}
|
||||
|
||||
$state = $this->state;
|
||||
|
||||
$state->previous->$entityType = $state->current->$entityType;
|
||||
$state->current->$entityType = $entities;
|
||||
}
|
||||
|
||||
public function setStateEntityType($entityType)
|
||||
{
|
||||
$state = $this->state;
|
||||
|
||||
if ($state->current->entityType == $entityType) {
|
||||
return;
|
||||
}
|
||||
|
||||
$state->previous->entityType = $state->current->entityType;
|
||||
$state->current->entityType = $entityType;
|
||||
}
|
||||
|
||||
public function stateEntities($entityType)
|
||||
{
|
||||
return $this->state->current->$entityType;
|
||||
}
|
||||
|
||||
public function stateEntity($entityType)
|
||||
{
|
||||
$entities = $this->state->current->$entityType;
|
||||
|
||||
return count($entities) ? $entities[0] : false;
|
||||
}
|
||||
|
||||
public function previousStateEntities($entityType)
|
||||
{
|
||||
return $this->state->previous->$entityType;
|
||||
}
|
||||
|
||||
public function stateEntityType()
|
||||
{
|
||||
return $this->state->current->entityType;
|
||||
}
|
||||
|
||||
|
||||
public function getState()
|
||||
{
|
||||
return $this->state;
|
||||
}
|
||||
|
||||
protected function requestClient()
|
||||
{
|
||||
$clientRepo = app('App\Ninja\Repositories\ClientRepository');
|
||||
$client = false;
|
||||
|
||||
foreach ($this->data->entities as $param) {
|
||||
if ($param->type == 'Name') {
|
||||
$client = $clientRepo->findPhonetically($param->entity);
|
||||
}
|
||||
}
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
protected function requestFields()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
if ( ! isset($this->data->compositeEntities)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($this->data->compositeEntities as $compositeEntity) {
|
||||
if ($compositeEntity->parentType != 'FieldValuePair') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field = false;
|
||||
$value = false;
|
||||
|
||||
foreach ($compositeEntity->children as $child) {
|
||||
if ($child->type == 'Field') {
|
||||
$field = $child->value;;
|
||||
} elseif ($child->type == 'Value') {
|
||||
$value = $child->value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($field && $value) {
|
||||
$field = $this->processField($field);
|
||||
$value = $this->processValue($value);
|
||||
|
||||
$data[$field] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->fieldMap as $key => $value) {
|
||||
if (isset($data[$key])) {
|
||||
$data[$value] = $data[$key];
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function processField($field)
|
||||
{
|
||||
$field = str_replace(' ', '_', $field);
|
||||
|
||||
if (strpos($field, 'date') !== false) {
|
||||
$field .= '_sql';
|
||||
}
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
protected function processValue($value)
|
||||
{
|
||||
// look for LUIS pre-built entity matches
|
||||
foreach ($this->data->entities as $entity) {
|
||||
if ($entity->entity === $value) {
|
||||
if ($entity->type == 'builtin.datetime.date') {
|
||||
$value = $entity->resolution->date;
|
||||
$value = str_replace('XXXX', date('Y'), $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function createResponse($type, $content)
|
||||
{
|
||||
$response = new SkypeResponse($type);
|
||||
|
||||
if (is_string($content)) {
|
||||
$response->setText($content);
|
||||
} else {
|
||||
if ($content instanceof \Illuminate\Database\Eloquent\Collection) {
|
||||
// do nothing
|
||||
} elseif ( ! is_array($content)) {
|
||||
$content = [$content];
|
||||
}
|
||||
|
||||
foreach ($content as $item) {
|
||||
$response->addAttachment($item);
|
||||
}
|
||||
}
|
||||
|
||||
return json_encode($response);
|
||||
}
|
||||
}
|
44
app/Ninja/Intents/CreateInvoiceIntent.php
Normal file
44
app/Ninja/Intents/CreateInvoiceIntent.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Exception;
|
||||
use App\Models\EntityModel;
|
||||
|
||||
class CreateInvoiceIntent extends InvoiceIntent
|
||||
{
|
||||
public function process()
|
||||
{
|
||||
$client = $this->requestClient();
|
||||
$invoiceItems = $this->requestInvoiceItems();
|
||||
|
||||
if ( ! $client) {
|
||||
throw new Exception(trans('texts.client_not_found'));
|
||||
}
|
||||
|
||||
$data = array_merge($this->requestFields(), [
|
||||
'client_id' => $client->id,
|
||||
'invoice_items' => $invoiceItems,
|
||||
]);
|
||||
|
||||
//var_dump($data);
|
||||
|
||||
$valid = EntityModel::validate($data, ENTITY_INVOICE);
|
||||
|
||||
if ($valid !== true) {
|
||||
throw new Exception($valid);
|
||||
}
|
||||
|
||||
$invoiceService = app('App\Services\InvoiceService');
|
||||
$invoice = $invoiceService->save($data);
|
||||
|
||||
$invoiceItemIds = array_map(function($item) {
|
||||
return $item['public_id'];
|
||||
}, $invoice->invoice_items->toArray());
|
||||
|
||||
$this->setStateEntityType(ENTITY_INVOICE);
|
||||
$this->setStateEntities(ENTITY_CLIENT, $client->public_id);
|
||||
$this->setStateEntities(ENTITY_INVOICE, $invoice->public_id);
|
||||
$this->setStateEntities(ENTITY_INVOICE_ITEM, $invoiceItemIds);
|
||||
|
||||
return $this->createResponse(SKYPE_CARD_RECEIPT, $invoice->present()->skypeBot);
|
||||
}
|
||||
}
|
19
app/Ninja/Intents/DownloadInvoiceIntent.php
Normal file
19
app/Ninja/Intents/DownloadInvoiceIntent.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Auth;
|
||||
use App\Models\EntityModel;
|
||||
use App\Models\Invoice;
|
||||
use App\Libraries\Skype\SkypeResponse;
|
||||
|
||||
class DownloadInvoiceIntent extends InvoiceIntent
|
||||
{
|
||||
public function process()
|
||||
{
|
||||
$invoice = $this->invoice();
|
||||
|
||||
$message = trans('texts.' . $invoice->getEntityType()) . ' ' . $invoice->invoice_number;
|
||||
$message = link_to('/download/' . $invoice->invitations[0]->invitation_key, $message);
|
||||
|
||||
return SkypeResponse::message($message);
|
||||
}
|
||||
}
|
32
app/Ninja/Intents/EmailInvoiceIntent.php
Normal file
32
app/Ninja/Intents/EmailInvoiceIntent.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Auth;
|
||||
use Exception;
|
||||
use App\Models\EntityModel;
|
||||
use App\Models\Invoice;
|
||||
use App\Libraries\Skype\SkypeResponse;
|
||||
|
||||
class EmailInvoiceIntent extends InvoiceIntent
|
||||
{
|
||||
public function process()
|
||||
{
|
||||
$invoice = $this->stateInvoice();
|
||||
|
||||
if ( ! Auth::user()->can('edit', $invoice)) {
|
||||
throw new Exception(trans('texts.not_allowed'));
|
||||
}
|
||||
|
||||
$contactMailer = app('App\Ninja\Mailers\ContactMailer');
|
||||
$contactMailer->sendInvoice($invoice);
|
||||
|
||||
$message = trans('texts.bot_emailed_' . $invoice->getEntityType());
|
||||
|
||||
if (Auth::user()->notify_viewed) {
|
||||
$message .= '<br/>' . trans('texts.bot_emailed_notify_viewed');
|
||||
} elseif (Auth::user()->notify_paid) {
|
||||
$message .= '<br/>' . trans('texts.bot_emailed_notify_paid');
|
||||
}
|
||||
|
||||
return SkypeResponse::message($message);
|
||||
}
|
||||
}
|
93
app/Ninja/Intents/InvoiceIntent.php
Normal file
93
app/Ninja/Intents/InvoiceIntent.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Auth;
|
||||
use Exception;
|
||||
use App\Models\Invoice;
|
||||
|
||||
class InvoiceIntent extends BaseIntent
|
||||
{
|
||||
protected $fieldMap = [
|
||||
'deposit' => 'partial',
|
||||
'due' => 'due_date',
|
||||
];
|
||||
|
||||
public function __construct($state, $data)
|
||||
{
|
||||
$this->invoiceRepo = app('App\Ninja\Repositories\InvoiceRepository');
|
||||
|
||||
parent::__construct($state, $data);
|
||||
}
|
||||
|
||||
protected function stateInvoice()
|
||||
{
|
||||
$invoiceId = $this->stateEntity(ENTITY_INVOICE);
|
||||
|
||||
if ( ! $invoiceId) {
|
||||
throw new Exception(trans('texts.intent_not_supported'));
|
||||
}
|
||||
|
||||
$invoice = Invoice::scope($invoiceId)->first();
|
||||
|
||||
if ( ! $invoice) {
|
||||
throw new Exception(trans('texts.intent_not_supported'));
|
||||
}
|
||||
|
||||
if ( ! Auth::user()->can('view', $invoice)) {
|
||||
throw new Exception(trans('texts.not_allowed'));
|
||||
}
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
||||
protected function requestInvoiceItems()
|
||||
{
|
||||
$productRepo = app('App\Ninja\Repositories\ProductRepository');
|
||||
|
||||
$invoiceItems = [];
|
||||
|
||||
if ( ! isset($this->data->compositeEntities) || ! count($this->data->compositeEntities)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($this->data->compositeEntities as $entity) {
|
||||
if ($entity->parentType == 'InvoiceItem') {
|
||||
$product = false;
|
||||
$qty = 1;
|
||||
foreach ($entity->children as $child) {
|
||||
if ($child->type == 'Product') {
|
||||
$product = $productRepo->findPhonetically($child->value);
|
||||
} else {
|
||||
$qty = $child->value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($product) {
|
||||
$item['qty'] = $qty;
|
||||
$item['product_key'] = $product->product_key;
|
||||
$item['cost'] = $product->cost;
|
||||
$item['notes'] = $product->notes;
|
||||
|
||||
if ($taxRate = $product->default_tax_rate) {
|
||||
$item['tax_name1'] = $taxRate->name;
|
||||
$item['tax_rate1'] = $taxRate->rate;
|
||||
}
|
||||
|
||||
$invoiceItems[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if ( ! count($invoiceItems)) {
|
||||
foreach ($this->data->entities as $param) {
|
||||
if ($param->type == 'Product') {
|
||||
$product = $productRepo->findPhonetically($param->entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return $invoiceItems;
|
||||
}
|
||||
|
||||
}
|
27
app/Ninja/Intents/ListProductsIntent.php
Normal file
27
app/Ninja/Intents/ListProductsIntent.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Auth;
|
||||
use Exception;
|
||||
use App\Models\Product;
|
||||
|
||||
|
||||
class ListProductsIntent extends ProductIntent
|
||||
{
|
||||
public function process()
|
||||
{
|
||||
$account = Auth::user()->account;
|
||||
$products = Product::scope()
|
||||
->orderBy('product_key')
|
||||
->limit(10)
|
||||
->get()
|
||||
->transform(function($item, $key) use ($account) {
|
||||
$card = $item->present()->skypeBot($account);
|
||||
if ($this->stateEntity(ENTITY_INVOICE)) {
|
||||
$card->addButton('imBack', trans('texts.add_to_invoice'), trans('texts.add_product_to_invoice', ['product' => $item->product_key]));
|
||||
}
|
||||
return $card;
|
||||
});
|
||||
|
||||
return $this->createResponse(SKYPE_CARD_CAROUSEL, $products);
|
||||
}
|
||||
}
|
15
app/Ninja/Intents/ProductIntent.php
Normal file
15
app/Ninja/Intents/ProductIntent.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Auth;
|
||||
use Exception;
|
||||
|
||||
|
||||
class ProductIntent extends BaseIntent
|
||||
{
|
||||
public function __construct($state, $data)
|
||||
{
|
||||
$this->productRepo = app('App\Ninja\Repositories\ProductRepository');
|
||||
|
||||
parent::__construct($state, $data);
|
||||
}
|
||||
}
|
54
app/Ninja/Intents/UpdateInvoiceIntent.php
Normal file
54
app/Ninja/Intents/UpdateInvoiceIntent.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php namespace App\Ninja\Intents;
|
||||
|
||||
use Exception;
|
||||
use App\Models\EntityModel;
|
||||
use App\Models\Invoice;
|
||||
|
||||
class UpdateInvoiceIntent extends InvoiceIntent
|
||||
{
|
||||
public function process()
|
||||
{
|
||||
$invoice = $this->stateInvoice();
|
||||
$invoiceItems = $this->requestInvoiceItems();
|
||||
|
||||
$data = array_merge($this->requestFields(), [
|
||||
'public_id' => $invoice->public_id,
|
||||
'invoice_items' => array_merge($invoice->invoice_items->toArray(), $invoiceItems),
|
||||
]);
|
||||
|
||||
// map the cost and qty fields to the invoice items
|
||||
if (isset($data['cost']) || isset($data['quantity'])) {
|
||||
foreach ($data['invoice_items'] as $key => $item) {
|
||||
// if it's new or we recently created it
|
||||
if (empty($item['public_id']) || in_array($item['public_id'], $this->entities(ENTITY_INVOICE_ITEM))) {
|
||||
$data['invoice_items'][$key]['cost'] = isset($data['cost']) ? $data['cost'] : $item['cost'];
|
||||
$data['invoice_items'][$key]['qty'] = isset($data['quantity']) ? $data['quantity'] : $item['qty'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//var_dump($data);
|
||||
|
||||
$valid = EntityModel::validate($data, ENTITY_INVOICE, $invoice);
|
||||
|
||||
if ($valid !== true) {
|
||||
throw new Exception($valid);
|
||||
}
|
||||
|
||||
$invoice = $this->invoiceRepo->save($data, $invoice);
|
||||
|
||||
$invoiceItems = array_slice($invoice->invoice_items->toArray(), count($invoiceItems) * -1);
|
||||
$invoiceItemIds = array_map(function($item) {
|
||||
return $item['public_id'];
|
||||
}, $invoiceItems);
|
||||
|
||||
$this->setStateEntities(ENTITY_INVOICE_ITEM, $invoiceItemIds);
|
||||
|
||||
$response = $invoice
|
||||
->load('invoice_items')
|
||||
->present()
|
||||
->skypeBot;
|
||||
|
||||
return $this->createResponse(SKYPE_CARD_RECEIPT, $response);
|
||||
}
|
||||
}
|
@ -109,4 +109,20 @@ class UserMailer extends Mailer
|
||||
|
||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
|
||||
public function sendSecurityCode($user, $code)
|
||||
{
|
||||
if (!$user->email) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = trans('texts.security_code_email_subject');
|
||||
$view = 'security_code';
|
||||
$data = [
|
||||
'userName' => $user->getDisplayName(),
|
||||
'code' => $code,
|
||||
];
|
||||
|
||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,11 @@ class BasePaymentDriver
|
||||
return $this->accountGateway->gateway_id == $gatewayId;
|
||||
}
|
||||
|
||||
public function isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// optionally pass a paymentMethod to determine the type from the token
|
||||
protected function isGatewayType($gatewayType, $paymentMethod = false)
|
||||
{
|
||||
@ -535,6 +540,15 @@ class BasePaymentDriver
|
||||
$paymentMethod->setRelation('account_gateway_token', $customer);
|
||||
$paymentMethod = $this->creatingPaymentMethod($paymentMethod);
|
||||
|
||||
// archive the old payment method
|
||||
$oldPaymentMethod = PaymentMethod::clientId($this->client()->id)
|
||||
->wherePaymentTypeId($paymentMethod->payment_type_id)
|
||||
->first();
|
||||
|
||||
if ($oldPaymentMethod) {
|
||||
$oldPaymentMethod->delete();
|
||||
}
|
||||
|
||||
if ($paymentMethod) {
|
||||
$paymentMethod->save();
|
||||
}
|
||||
@ -753,7 +767,7 @@ class BasePaymentDriver
|
||||
} elseif ($paymentMethod->payment_type_id == PAYMENT_TYPE_PAYPAL) {
|
||||
$label = 'PayPal: ' . $paymentMethod->email;
|
||||
} else {
|
||||
$label = trans('texts.use_card_on_file');
|
||||
$label = trans('texts.payment_type_on_file', ['type' => $paymentMethod->payment_type->name]);
|
||||
}
|
||||
|
||||
$links[] = [
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php namespace App\Ninja\PaymentDrivers;
|
||||
|
||||
use Exception;
|
||||
|
||||
class MolliePaymentDriver extends BasePaymentDriver
|
||||
{
|
||||
public function completeOffsitePurchase($input)
|
||||
@ -10,6 +12,12 @@ class MolliePaymentDriver extends BasePaymentDriver
|
||||
|
||||
$response = $this->gateway()->fetchTransaction($details)->send();
|
||||
|
||||
if ($response->isCancelled()) {
|
||||
return false;
|
||||
} elseif ( ! $response->isSuccessful()) {
|
||||
throw new Exception($response->getMessage());
|
||||
}
|
||||
|
||||
return $this->createPayment($response->getTransactionReference());
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,21 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function isValid()
|
||||
{
|
||||
$result = $this->makeStripeCall(
|
||||
'GET',
|
||||
'charges',
|
||||
'limit=1'
|
||||
);
|
||||
|
||||
if (array_get($result, 'object') == 'list') {
|
||||
return true;
|
||||
} else {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
protected function checkCustomerExists($customer)
|
||||
{
|
||||
$response = $this->gateway()
|
||||
@ -347,15 +362,15 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
$eventDetails = $this->makeStripeCall('GET', 'events/'.$eventId);
|
||||
|
||||
if (is_string($eventDetails) || !$eventDetails) {
|
||||
throw new Exception('Could not get event details');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($eventType != $eventDetails['type']) {
|
||||
throw new Exception('Event type mismatch');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$eventDetails['pending_webhooks']) {
|
||||
throw new Exception('This is not a pending event');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($eventType == 'charge.failed' || $eventType == 'charge.succeeded' || $eventType == 'charge.refunded') {
|
||||
@ -365,7 +380,7 @@ class StripePaymentDriver extends BasePaymentDriver
|
||||
$payment = Payment::scope(false, $accountId)->where('transaction_reference', '=', $transactionRef)->first();
|
||||
|
||||
if (!$payment) {
|
||||
throw new Exception('Unknown payment');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($eventType == 'charge.failed') {
|
||||
|
@ -8,6 +8,22 @@ class ClientPresenter extends EntityPresenter {
|
||||
return $this->entity->country ? $this->entity->country->name : '';
|
||||
}
|
||||
|
||||
public function balance()
|
||||
{
|
||||
$client = $this->entity;
|
||||
$account = $client->account;
|
||||
|
||||
return $account->formatMoney($client->balance, $client);
|
||||
}
|
||||
|
||||
public function paid_to_date()
|
||||
{
|
||||
$client = $this->entity;
|
||||
$account = $client->account;
|
||||
|
||||
return $account->formatMoney($client->paid_to_date, $client);
|
||||
}
|
||||
|
||||
public function status()
|
||||
{
|
||||
$class = $text = '';
|
||||
|
@ -5,7 +5,6 @@ use Laracasts\Presenter\Presenter;
|
||||
|
||||
class EntityPresenter extends Presenter
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php namespace App\Ninja\Presenters;
|
||||
|
||||
use Utils;
|
||||
use App\Libraries\Skype\InvoiceCard;
|
||||
|
||||
class InvoicePresenter extends EntityPresenter {
|
||||
|
||||
@ -14,6 +15,22 @@ class InvoicePresenter extends EntityPresenter {
|
||||
return $this->entity->user->getDisplayName();
|
||||
}
|
||||
|
||||
public function amount()
|
||||
{
|
||||
$invoice = $this->entity;
|
||||
$account = $invoice->account;
|
||||
|
||||
return $account->formatMoney($invoice->amount, $invoice->client);
|
||||
}
|
||||
|
||||
public function requestedAmount()
|
||||
{
|
||||
$invoice = $this->entity;
|
||||
$account = $invoice->account;
|
||||
|
||||
return $account->formatMoney($invoice->getRequestedAmount(), $invoice->client);
|
||||
}
|
||||
|
||||
public function balanceDueLabel()
|
||||
{
|
||||
if ($this->entity->partial > 0) {
|
||||
@ -25,6 +42,26 @@ class InvoicePresenter extends EntityPresenter {
|
||||
}
|
||||
}
|
||||
|
||||
public function dueDateLabel()
|
||||
{
|
||||
if ($this->entity->isType(INVOICE_TYPE_STANDARD)) {
|
||||
return trans('texts.due_date');
|
||||
} else {
|
||||
return trans('texts.valid_until');
|
||||
}
|
||||
}
|
||||
|
||||
public function discount()
|
||||
{
|
||||
$invoice = $this->entity;
|
||||
|
||||
if ($invoice->is_amount_discount) {
|
||||
return $invoice->account->formatMoney($invoice->discount);
|
||||
} else {
|
||||
return $invoice->discount . '%';
|
||||
}
|
||||
}
|
||||
|
||||
// https://schema.org/PaymentStatusType
|
||||
public function paymentStatus()
|
||||
{
|
||||
@ -99,4 +136,9 @@ class InvoicePresenter extends EntityPresenter {
|
||||
|
||||
return trans('texts.auto_bill_notification', $data);
|
||||
}
|
||||
|
||||
public function skypeBot()
|
||||
{
|
||||
return new InvoiceCard($this->entity);
|
||||
}
|
||||
}
|
||||
|
20
app/Ninja/Presenters/ProductPresenter.php
Normal file
20
app/Ninja/Presenters/ProductPresenter.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php namespace App\Ninja\Presenters;
|
||||
|
||||
use App\Libraries\Skype\HeroCard;
|
||||
|
||||
class ProductPresenter extends EntityPresenter
|
||||
{
|
||||
|
||||
public function skypeBot($account)
|
||||
{
|
||||
$product = $this->entity;
|
||||
|
||||
$card = new HeroCard();
|
||||
$card->setTitle($product->product_key);
|
||||
$card->setSubitle($account->formatMoney($product->cost));
|
||||
$card->setText($product->notes);
|
||||
|
||||
return $card;
|
||||
}
|
||||
|
||||
}
|
@ -132,4 +132,47 @@ class ClientRepository extends BaseRepository
|
||||
|
||||
return $client;
|
||||
}
|
||||
|
||||
public function findPhonetically($clientName)
|
||||
{
|
||||
$clientNameMeta = metaphone($clientName);
|
||||
|
||||
$map = [];
|
||||
$max = SIMILAR_MIN_THRESHOLD;
|
||||
$clientId = 0;
|
||||
|
||||
$clients = Client::scope()->get(['id', 'name', 'public_id']);
|
||||
|
||||
foreach ($clients as $client) {
|
||||
if ( ! $client->name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$map[$client->id] = $client;
|
||||
$similar = similar_text($clientNameMeta, metaphone($client->name), $percent);
|
||||
|
||||
if ($percent > $max) {
|
||||
$clientId = $client->id;
|
||||
$max = $percent;
|
||||
}
|
||||
}
|
||||
|
||||
$contacts = Contact::scope()->get(['client_id', 'first_name', 'last_name', 'public_id']);
|
||||
|
||||
foreach ($contacts as $contact) {
|
||||
if ( ! $contact->getFullName() || ! isset($map[$contact->client_id])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$similar = similar_text($clientNameMeta, metaphone($contact->getFullName()), $percent);
|
||||
|
||||
if ($percent > $max) {
|
||||
$clientId = $contact->client_id;
|
||||
$max = $percent;
|
||||
}
|
||||
}
|
||||
|
||||
return ($clientId && isset($map[$clientId])) ? $map[$clientId] : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ class InvoiceRepository extends BaseRepository
|
||||
|
||||
if ($invoice) {
|
||||
// do nothing
|
||||
$entityType = $invoice->getEntityType();
|
||||
} elseif ($isNew) {
|
||||
$entityType = ENTITY_INVOICE;
|
||||
if (isset($data['is_recurring']) && filter_var($data['is_recurring'], FILTER_VALIDATE_BOOLEAN)) {
|
||||
@ -270,6 +271,7 @@ class InvoiceRepository extends BaseRepository
|
||||
$entityType = ENTITY_QUOTE;
|
||||
}
|
||||
$invoice = $account->createInvoice($entityType, $data['client_id']);
|
||||
$invoice->invoice_date = date_create()->format('Y-m-d');
|
||||
if (isset($data['has_tasks']) && filter_var($data['has_tasks'], FILTER_VALIDATE_BOOLEAN)) {
|
||||
$invoice->has_tasks = true;
|
||||
}
|
||||
|
@ -56,4 +56,34 @@ class ProductRepository extends BaseRepository
|
||||
return $product;
|
||||
}
|
||||
|
||||
public function findPhonetically($productName)
|
||||
{
|
||||
$productNameMeta = metaphone($productName);
|
||||
|
||||
$map = [];
|
||||
$max = SIMILAR_MIN_THRESHOLD;
|
||||
$productId = 0;
|
||||
|
||||
$products = Product::scope()
|
||||
->with('default_tax_rate')
|
||||
->get();
|
||||
|
||||
foreach ($products as $product) {
|
||||
if ( ! $product->product_key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$map[$product->id] = $product;
|
||||
$similar = similar_text($productNameMeta, metaphone($product->product_key), $percent);
|
||||
|
||||
if ($percent > $max) {
|
||||
$productId = $product->id;
|
||||
$max = $percent;
|
||||
}
|
||||
}
|
||||
|
||||
return ($productId && isset($map[$productId])) ? $map[$productId] : null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class InvoiceTransformer extends EntityTransformer
|
||||
public function includeInvoiceItems(Invoice $invoice)
|
||||
{
|
||||
$transformer = new InvoiceItemTransformer($this->account, $this->serializer);
|
||||
return $this->includeCollection($invoice->invoice_items, $transformer, ENTITY_INVOICE_ITEMS);
|
||||
return $this->includeCollection($invoice->invoice_items, $transformer, ENTITY_INVOICE_ITEM);
|
||||
}
|
||||
|
||||
public function includeInvitations(Invoice $invoice)
|
||||
|
@ -29,4 +29,4 @@ class UserTransformer extends EntityTransformer
|
||||
'permissions' => (int) $user->getOriginal('permissions'),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
@ -45,7 +45,7 @@ class EntityPolicy
|
||||
* @param $ownerUserId
|
||||
* @return bool
|
||||
*/
|
||||
public static function viewByOwner(User$user, $ownerUserId) {
|
||||
public static function viewByOwner(User $user, $ownerUserId) {
|
||||
return $user->hasPermission('view_all') || $user->id == $ownerUserId;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,11 @@ class ComposerServiceProvider extends ServiceProvider
|
||||
['accounts.details', 'clients.edit', 'payments.edit', 'invoices.edit', 'accounts.localization'],
|
||||
'App\Http\ViewComposers\TranslationComposer'
|
||||
);
|
||||
|
||||
view()->composer(
|
||||
['header', 'tasks.edit'],
|
||||
'App\Http\ViewComposers\AppLanguageComposer'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -28,4 +33,4 @@ class ComposerServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class BaseService
|
||||
$entities = $this->getRepo()->findByPublicIdsWithTrashed($ids);
|
||||
|
||||
foreach ($entities as $entity) {
|
||||
if(Auth::user()->can('edit', $entity)){
|
||||
if (Auth::user()->can('edit', $entity)) {
|
||||
$this->getRepo()->$action($entity);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use Auth;
|
||||
use Utils;
|
||||
use parsecsv;
|
||||
use Session;
|
||||
use Validator;
|
||||
use League\Fractal\Manager;
|
||||
use App\Ninja\Repositories\ContactRepository;
|
||||
use App\Ninja\Repositories\ClientRepository;
|
||||
@ -141,7 +140,7 @@ class ImportService
|
||||
|
||||
foreach ($json['clients'] as $jsonClient) {
|
||||
|
||||
if ($this->validate($jsonClient, ENTITY_CLIENT) === true) {
|
||||
if (EntityModel::validate($jsonClient, ENTITY_CLIENT) === true) {
|
||||
$client = $this->clientRepo->save($jsonClient);
|
||||
$this->addSuccess($client);
|
||||
} else {
|
||||
@ -151,7 +150,7 @@ class ImportService
|
||||
|
||||
foreach ($jsonClient['invoices'] as $jsonInvoice) {
|
||||
$jsonInvoice['client_id'] = $client->id;
|
||||
if ($this->validate($jsonInvoice, ENTITY_INVOICE) === true) {
|
||||
if (EntityModel::validate($jsonInvoice, ENTITY_INVOICE) === true) {
|
||||
$invoice = $this->invoiceRepo->save($jsonInvoice);
|
||||
$this->addSuccess($invoice);
|
||||
} else {
|
||||
@ -162,7 +161,7 @@ class ImportService
|
||||
foreach ($jsonInvoice['payments'] as $jsonPayment) {
|
||||
$jsonPayment['client_id'] = $jsonPayment['client'] = $client->id; // TODO: change to client_id once views are updated
|
||||
$jsonPayment['invoice_id'] = $jsonPayment['invoice'] = $invoice->id; // TODO: change to invoice_id once views are updated
|
||||
if ($this->validate($jsonPayment, ENTITY_PAYMENT) === true) {
|
||||
if (EntityModel::validate($jsonPayment, ENTITY_PAYMENT) === true) {
|
||||
$payment = $this->paymentRepo->save($jsonPayment);
|
||||
$this->addSuccess($payment);
|
||||
} else {
|
||||
@ -280,7 +279,7 @@ class ImportService
|
||||
$data['invoice_number'] = $account->getNextInvoiceNumber($invoice);
|
||||
}
|
||||
|
||||
if ($this->validate($data, $entityType) !== true) {
|
||||
if (EntityModel::validate($data, $entityType) !== true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -396,26 +395,6 @@ class ImportService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $entityType
|
||||
* @return bool|string
|
||||
*/
|
||||
private function validate($data, $entityType)
|
||||
{
|
||||
$requestClass = 'App\\Http\\Requests\\Create' . ucwords($entityType) . 'Request';
|
||||
$request = new $requestClass();
|
||||
$request->setUserResolver(function() { return Auth::user(); });
|
||||
$request->replace($data);
|
||||
|
||||
$validator = Validator::make($data, $request->rules());
|
||||
|
||||
if ($validator->fails()) {
|
||||
return $validator->messages()->first();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $files
|
||||
|
@ -57,6 +57,21 @@ class PaymentService extends BaseService
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($credits = $client->credits->sum('balance')) {
|
||||
$balance = $invoice->balance;
|
||||
$amount = min($credits, $balance);
|
||||
$data = [
|
||||
'payment_type_id' => PAYMENT_TYPE_CREDIT,
|
||||
'invoice_id' => $invoice->id,
|
||||
'client_id' => $client->id,
|
||||
'amount' => $amount,
|
||||
];
|
||||
$payment = $this->paymentRepo->save($data);
|
||||
if ($amount == $balance) {
|
||||
return $payment;
|
||||
}
|
||||
}
|
||||
|
||||
$paymentDriver = $account->paymentDriver($invitation, GATEWAY_TYPE_TOKEN);
|
||||
|
||||
if ( ! $paymentDriver) {
|
||||
|
@ -154,4 +154,4 @@ class PushService
|
||||
else
|
||||
return trans('texts.notification_invoice_viewed_subject', ['invoice' => $invoice->invoice_number, 'client' => $invoice->client->name]);
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"dependencies": {
|
||||
"jquery": "1.11.3",
|
||||
"bootstrap": "3.3.1",
|
||||
"bootstrap-combobox": "1.1.5",
|
||||
"jquery-ui": "1.11.2",
|
||||
"datatables": "1.10.4",
|
||||
"datatables-bootstrap3": "*",
|
||||
@ -27,7 +28,8 @@
|
||||
"datetimepicker": "~2.4.5",
|
||||
"stacktrace-js": "~1.0.1",
|
||||
"fuse.js": "~2.0.2",
|
||||
"dropzone": "~4.3.0"
|
||||
"dropzone": "~4.3.0",
|
||||
"sweetalert": "~1.1.3"
|
||||
},
|
||||
"resolutions": {
|
||||
"jquery": "~1.11"
|
||||
|
@ -13,6 +13,10 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"ext-mcrypt": "*",
|
||||
"ext-gmp": "*",
|
||||
"ext-gd": "*",
|
||||
"turbo124/laravel-push-notification": "dev-laravel5",
|
||||
"omnipay/mollie": "dev-master#22956c1a62a9662afa5f5d119723b413770ac525",
|
||||
"omnipay/2checkout": "dev-master#e9c079c2dde0d7ba461903b3b7bd5caf6dee1248",
|
||||
|
@ -17,16 +17,16 @@ class AddPageSize extends Migration
|
||||
$table->boolean('live_preview')->default(true);
|
||||
$table->smallInteger('invoice_number_padding')->default(4);
|
||||
});
|
||||
|
||||
|
||||
Schema::table('fonts', function ($table) {
|
||||
$table->dropColumn('is_early_access');
|
||||
});
|
||||
|
||||
|
||||
Schema::create('expense_categories', function($table)
|
||||
{
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('account_id')->index();
|
||||
$table->unsignedInteger('account_id')->index();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
|
||||
@ -34,15 +34,14 @@ class AddPageSize extends Migration
|
||||
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
|
||||
|
||||
$table->unsignedInteger('public_id')->index();
|
||||
$table->unique( array('account_id','public_id') );
|
||||
});
|
||||
|
||||
|
||||
Schema::table('expenses', function ($table) {
|
||||
$table->unsignedInteger('expense_category_id')->nullable()->index();
|
||||
|
||||
$table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade');
|
||||
//$table->foreign('expense_category_id')->references('id')->on('expense_categories')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
@ -62,12 +61,12 @@ class AddPageSize extends Migration
|
||||
Schema::table('fonts', function ($table) {
|
||||
$table->boolean('is_early_access');
|
||||
});
|
||||
|
||||
|
||||
Schema::table('expenses', function ($table) {
|
||||
$table->dropForeign('expenses_expense_category_id_foreign');
|
||||
$table->dropColumn('expense_category_id');
|
||||
});
|
||||
|
||||
|
||||
Schema::dropIfExists('expense_categories');
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ class PaymentsChanges extends Migration
|
||||
$table->string('email')->nullable();
|
||||
|
||||
$table->unsignedInteger('payment_method_id')->nullable();
|
||||
$table->foreign('payment_method_id')->references('id')->on('payment_methods');
|
||||
//$table->foreign('payment_method_id')->references('id')->on('payment_methods');
|
||||
});
|
||||
|
||||
Schema::table('invoices', function($table)
|
||||
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddSupportForBots extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('security_codes', function($table)
|
||||
{
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('account_id')->index();
|
||||
$table->unsignedInteger('user_id')->nullable();
|
||||
$table->unsignedInteger('contact_id')->nullable();
|
||||
$table->smallInteger('attempts');
|
||||
$table->string('code')->nullable();
|
||||
$table->string('bot_user_id')->unique();
|
||||
$table->timestamp('created_at')->useCurrent();
|
||||
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
$table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
|
||||
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
});
|
||||
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->string('bot_user_id')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('contacts', function($table)
|
||||
{
|
||||
$table->string('bot_user_id')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('accounts', function($table)
|
||||
{
|
||||
$table->boolean('include_item_taxes_inline')->default(false);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('security_codes');
|
||||
|
||||
Schema::table('users', function($table)
|
||||
{
|
||||
$table->dropColumn('bot_user_id');
|
||||
});
|
||||
|
||||
Schema::table('contacts', function($table)
|
||||
{
|
||||
$table->dropColumn('bot_user_id');
|
||||
});
|
||||
|
||||
Schema::table('accounts', function($table)
|
||||
{
|
||||
$table->dropColumn('include_item_taxes_inline');
|
||||
});
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ class DateFormatsSeeder extends Seeder
|
||||
];
|
||||
|
||||
foreach ($formats as $format) {
|
||||
$record = DatetimeFormat::whereFormat($format['format'])->first();
|
||||
$record = DatetimeFormat::whereRaw("BINARY `format`= ?", array($format['format']))->first();
|
||||
if ($record) {
|
||||
$record->format_moment = $format['format_moment'];
|
||||
$record->save();
|
||||
|
@ -33,5 +33,5 @@ class PaymentStatusSeeder extends Seeder
|
||||
PaymentStatus::create($status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
gulpfile.js
100
gulpfile.js
@ -1,16 +1,96 @@
|
||||
var elixir = require('laravel-elixir');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Elixir Asset Management
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
|
||||
| for your Laravel application. By default, we are compiling the Less
|
||||
| file for our application, as well as publishing vendor resources.
|
||||
|
|
||||
/**
|
||||
* Set Elixir Source Maps
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
elixir.config.sourcemaps = true;
|
||||
|
||||
/**
|
||||
* Configuring assets path.
|
||||
* Explicitly setting it to empty, as we're not using Laravels resources/assets folder
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
elixir.config.assetsPath = '';
|
||||
|
||||
/**
|
||||
* Configuring Javascript assets path.
|
||||
* Explicitly setting it to empty, as we're not using Laravels resources/assets/js folder
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
elixir.config.js.folder = '';
|
||||
|
||||
/**
|
||||
* Configuring CSS assets path.
|
||||
* Explicitly setting it to empty, as we're not using Laravels resources/assets/css folder
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
elixir.config.css.folder = '';
|
||||
|
||||
/**
|
||||
* Remove all CSS comments
|
||||
*
|
||||
* @type {{discardComments: {removeAll: boolean}}}
|
||||
*/
|
||||
elixir.config.css.minifier.pluginOptions = {
|
||||
discardComments: {
|
||||
removeAll: true
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Directory for bower source files.
|
||||
* If changing this, please also see .bowerrc
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
var bowerDir = 'public/vendor';
|
||||
|
||||
elixir(function(mix) {
|
||||
mix.less('app.less');
|
||||
|
||||
/**
|
||||
* CSS configuration
|
||||
*/
|
||||
mix.styles([
|
||||
bowerDir + '/bootstrap/dist/css/bootstrap.css',
|
||||
bowerDir + '/font-awesome/css/font-awesome.css',
|
||||
bowerDir + '/datatables/media/css/jquery.dataTables.css',
|
||||
bowerDir + '/datatables-bootstrap3/BS3/assets/css/datatables.css',
|
||||
'public/css/bootstrap-combobox.css',
|
||||
'public/css/public.style.css'
|
||||
], 'public/css/built.public.css');
|
||||
|
||||
mix.styles([
|
||||
bowerDir + '/bootstrap/dist/css/bootstrap.css',
|
||||
bowerDir + '/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css',
|
||||
bowerDir + '/datatables/media/css/jquery.dataTables.css',
|
||||
bowerDir + '/datatables-bootstrap3/BS3/assets/css/datatables.css',
|
||||
bowerDir + '/font-awesome/css/font-awesome.css',
|
||||
bowerDir + '/dropzone/dist/dropzone.css',
|
||||
bowerDir + '/spectrum/spectrum.css',
|
||||
bowerDir + '/sweetalert/dist/sweetalert.css',
|
||||
'public/css/bootstrap-combobox.css',
|
||||
'public/css/typeahead.js-bootstrap.css',
|
||||
'public/css/style.css'
|
||||
], 'public/css/built.css');
|
||||
|
||||
/**
|
||||
* JS configuration
|
||||
*/
|
||||
mix.scripts(['resources/assets/js/Chart.js'], 'public/js/Chart.min.js')
|
||||
.scripts(['resources/assets/js/d3.js'], 'public/js/d3.min.js');
|
||||
|
||||
mix.scripts([
|
||||
'public/js/pdf_viewer.js',
|
||||
'public/js/compatibility.js',
|
||||
//'public/js/pdfmake.min.js',
|
||||
'public/js/pdfmake.js',
|
||||
'public/js/vfs.js'
|
||||
], 'public/pdf.built.js');
|
||||
|
||||
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"grunt-dump-dir": "^0.1.2",
|
||||
"gulp": "^3.8.8",
|
||||
"laravel-elixir": "*"
|
||||
"laravel-elixir": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"grunt-dump-dir": "^0.1.2"
|
||||
|
BIN
public/android-chrome-192x192.png
Normal file
BIN
public/android-chrome-192x192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
public/android-chrome-512x512.png
Normal file
BIN
public/android-chrome-512x512.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 12 KiB |
File diff suppressed because one or more lines are too long
1
public/built.js.map
Normal file
1
public/built.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
public/css/app.min.css
vendored
Normal file
3
public/css/app.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/app.min.css.map
Normal file
1
public/css/app.min.css.map
Normal file
File diff suppressed because one or more lines are too long
1
public/css/bootstrap.min.css.map
Normal file
1
public/css/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
3235
public/css/built.css
vendored
3235
public/css/built.css
vendored
File diff suppressed because one or more lines are too long
1
public/css/built.css.map
Normal file
1
public/css/built.css.map
Normal file
File diff suppressed because one or more lines are too long
21
public/css/built.min.css
vendored
Normal file
21
public/css/built.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/built.min.css.map
Normal file
1
public/css/built.min.css.map
Normal file
File diff suppressed because one or more lines are too long
971
public/css/built.public.css
vendored
971
public/css/built.public.css
vendored
File diff suppressed because one or more lines are too long
1
public/css/built.public.css.map
Normal file
1
public/css/built.public.css.map
Normal file
File diff suppressed because one or more lines are too long
14
public/css/built.public.min.css
vendored
Normal file
14
public/css/built.public.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/built.public.min.css.map
Normal file
1
public/css/built.public.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
public/css/customCss.min.css
vendored
Normal file
2
public/css/customCss.min.css
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.customContainer{padding:40px 0;margin:0!important;background:-webkit-linear-gradient(#f5f5f5,#fff)}.customFontHead{font-size:20px;text-align:center}.customTextBorder{border-bottom:1px solid #c3c1c1;padding-bottom:5%;margin-bottom:5%}.customSubMenu{margin-left:2%}.customMenuOne{padding-left:5px;padding-right:5px}.shiftLeft{float:left}.customMenuDiv{padding-bottom:30px;float:left;width:100%}
|
||||
/*# sourceMappingURL=customCss.min.css.map */
|
1
public/css/customCss.min.css.map
Normal file
1
public/css/customCss.min.css.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["customCss.css"],"names":[],"mappings":"AAAA,iBACA,eAAA,AACA,mBAAA,AACA,gDAAA,CACA,AACA,gBACA,eAAA,AACA,iBAAA,CACA,AACA,kBACA,gCAAA,AACA,kBAAA,AACA,gBAAA,CACA,AACA,eACA,cAAA,CACA,AACA,eACA,iBAAA,AACA,iBAAA,CACA,AACA,WACA,UAAA,CACA,AACA,eACA,oBAAA,AACA,WAAA,AACA,UAAA,CACA","file":"customCss.min.css","sourcesContent":[".customContainer{\n\tpadding: 40px 0;\n\tmargin: 0px 0 !important;\n\tbackground: -webkit-linear-gradient(rgb(245, 245, 245), white);\n}\t\n.customFontHead{\n\tfont-size: 20px;\n\ttext-align: center;\n}\t\n.customTextBorder{\n\tborder-bottom: 1px solid rgb(195, 193, 193);\n\tpadding-bottom: 5%;\n\tmargin-bottom: 5%;\n}\n.customSubMenu{\n\tmargin-left: 2%;\n}\n.customMenuOne{\n\tpadding-left: 5px;\n\tpadding-right: 5px;\n}\n.shiftLeft{\n\tfloat: left;\n}\n.customMenuDiv{\n\tpadding-bottom: 30px;\n\tfloat: left;\n\twidth: 100%;\n}"],"sourceRoot":"/source/"}
|
893
public/css/img/jsoneditor-icons.svg
Normal file
893
public/css/img/jsoneditor-icons.svg
Normal file
@ -0,0 +1,893 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="216"
|
||||
height="144"
|
||||
id="svg4136"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r"
|
||||
sodipodi:docname="jsoneditor-icons.svg">
|
||||
<title
|
||||
id="title6512">JSON Editor Icons</title>
|
||||
<metadata
|
||||
id="metadata4148">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title>JSON Editor Icons</dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs4146" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1028"
|
||||
id="namedview4144"
|
||||
showgrid="true"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="97.217248"
|
||||
inkscape:cy="59.950227"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4136"
|
||||
showguides="false"
|
||||
borderlayer="false"
|
||||
inkscape:showpageshadow="true"
|
||||
showborder="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4640"
|
||||
empspacing="24" />
|
||||
</sodipodi:namedview>
|
||||
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
|
||||
<g
|
||||
id="g4394">
|
||||
<rect
|
||||
x="4"
|
||||
y="4"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg_1"
|
||||
style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0"
|
||||
x="28.000006"
|
||||
y="3.999995"
|
||||
width="16"
|
||||
height="16"
|
||||
id="svg_1-7" />
|
||||
<rect
|
||||
id="rect4165"
|
||||
height="16"
|
||||
width="16"
|
||||
y="3.999995"
|
||||
x="52.000004"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
x="172.00002"
|
||||
y="3.9999852"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4175" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
x="196"
|
||||
y="3.999995"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4175-3" />
|
||||
<g
|
||||
style="stroke:none"
|
||||
id="g4299">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1-1"
|
||||
height="1.9999986"
|
||||
width="9.9999924"
|
||||
y="10.999998"
|
||||
x="7.0000048" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1-1-1"
|
||||
height="9.9999838"
|
||||
width="1.9999955"
|
||||
y="7.0000114"
|
||||
x="11.000005" />
|
||||
</g>
|
||||
<g
|
||||
style="stroke:none"
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
|
||||
id="g4299-3">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1-1-0"
|
||||
height="1.9999986"
|
||||
width="9.9999924"
|
||||
y="10.999998"
|
||||
x="7.0000048" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="svg_1-1-1-9"
|
||||
height="9.9999838"
|
||||
width="1.9999955"
|
||||
y="7.0000114"
|
||||
x="11.000005" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="55.000004"
|
||||
y="7.0000048"
|
||||
width="6.9999909"
|
||||
height="6.9999905"
|
||||
id="svg_1-7-5" />
|
||||
<rect
|
||||
id="rect4354"
|
||||
height="6.9999905"
|
||||
width="6.9999909"
|
||||
y="10.00001"
|
||||
x="58"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
|
||||
x="58.000004"
|
||||
y="10.000005"
|
||||
width="6.9999909"
|
||||
height="6.9999905"
|
||||
id="svg_1-7-5-7" />
|
||||
<g
|
||||
id="g4378">
|
||||
<rect
|
||||
id="svg_1-7-5-3"
|
||||
height="1.9999965"
|
||||
width="7.9999909"
|
||||
y="10.999999"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="7.0000005"
|
||||
width="11.999995"
|
||||
height="1.9999946"
|
||||
id="rect4374" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="14.999996"
|
||||
width="3.9999928"
|
||||
height="1.9999995"
|
||||
id="rect4376" />
|
||||
</g>
|
||||
<g
|
||||
id="g4383"
|
||||
transform="matrix(1,0,0,-1,-23.999995,23.999995)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="10.999999"
|
||||
width="7.9999909"
|
||||
height="1.9999965"
|
||||
id="rect4385" />
|
||||
<rect
|
||||
id="rect4387"
|
||||
height="1.9999946"
|
||||
width="11.999995"
|
||||
y="7.0000005"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4389"
|
||||
height="1.9999995"
|
||||
width="3.9999928"
|
||||
y="14.999996"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
</g>
|
||||
<rect
|
||||
y="3.9999199"
|
||||
x="76"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect3754-4"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4351"
|
||||
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4351-9"
|
||||
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
y="3.9999199"
|
||||
x="100"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect3754-25"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2987"
|
||||
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2987-1"
|
||||
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="3.9999199"
|
||||
x="124"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect3754-73"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3780"
|
||||
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3782"
|
||||
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
|
||||
<rect
|
||||
y="3.9999199"
|
||||
x="148"
|
||||
height="16"
|
||||
width="16"
|
||||
id="rect3754-35"
|
||||
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5008-2"
|
||||
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path5008-2-8"
|
||||
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
<rect
|
||||
x="4"
|
||||
y="27.999994"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4432"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
x="28.000006"
|
||||
y="27.99999"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4434" />
|
||||
<rect
|
||||
id="rect4436"
|
||||
height="16"
|
||||
width="16"
|
||||
y="27.99999"
|
||||
x="52.000004"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
|
||||
x="172.00002"
|
||||
y="27.999981"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4446" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
|
||||
x="196"
|
||||
y="27.99999"
|
||||
width="16"
|
||||
height="16"
|
||||
id="rect4448" />
|
||||
<g
|
||||
id="g4466"
|
||||
style="stroke:none"
|
||||
transform="translate(0,23.999995)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="rect4468"
|
||||
height="1.9999986"
|
||||
width="9.9999924"
|
||||
y="10.999998"
|
||||
x="7.0000048" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="rect4470"
|
||||
height="9.9999838"
|
||||
width="1.9999955"
|
||||
y="7.0000114"
|
||||
x="11.000005" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,35.999996)"
|
||||
id="g4472"
|
||||
style="stroke:none">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="rect4474"
|
||||
height="1.9999986"
|
||||
width="9.9999924"
|
||||
y="10.999998"
|
||||
x="7.0000048" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
|
||||
id="rect4476"
|
||||
height="9.9999838"
|
||||
width="1.9999955"
|
||||
y="7.0000114"
|
||||
x="11.000005" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="55.000004"
|
||||
y="31"
|
||||
width="6.9999909"
|
||||
height="6.9999905"
|
||||
id="rect4478" />
|
||||
<rect
|
||||
id="rect4480"
|
||||
height="6.9999905"
|
||||
width="6.9999909"
|
||||
y="34.000008"
|
||||
x="58"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
x="58.000004"
|
||||
y="34.000004"
|
||||
width="6.9999909"
|
||||
height="6.9999905"
|
||||
id="rect4482" />
|
||||
<g
|
||||
id="g4484"
|
||||
transform="translate(0,23.999995)">
|
||||
<rect
|
||||
id="rect4486"
|
||||
height="1.9999965"
|
||||
width="7.9999909"
|
||||
y="10.999999"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="7.0000005"
|
||||
width="11.999995"
|
||||
height="1.9999946"
|
||||
id="rect4488" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="14.999996"
|
||||
width="3.9999928"
|
||||
height="1.9999995"
|
||||
id="rect4490" />
|
||||
</g>
|
||||
<g
|
||||
id="g4492"
|
||||
transform="matrix(1,0,0,-1,-23.999995,47.99999)">
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
|
||||
x="198"
|
||||
y="10.999999"
|
||||
width="7.9999909"
|
||||
height="1.9999965"
|
||||
id="rect4494" />
|
||||
<rect
|
||||
id="rect4496"
|
||||
height="1.9999946"
|
||||
width="11.999995"
|
||||
y="7.0000005"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4498"
|
||||
height="1.9999995"
|
||||
width="3.9999928"
|
||||
y="14.999996"
|
||||
x="198"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
|
||||
id="rect3754-8"
|
||||
width="16"
|
||||
height="16"
|
||||
x="76"
|
||||
y="27.99992" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 85.10448,30.015537 -0.0156,1.4063 c 3.02668,-0.2402 0.33007,3.6508 2.48438,4.5781 -2.18695,1.0938 0.49191,4.90688 -2.45313,4.57808 l -0.0156,1.4219 c 5.70827,0.559 1.03263,-5.10048 4.70313,-5.26558 l 0,-1.4063 c -3.61304,-0.027 1.11893,-5.707 -4.70313,-5.3125 z"
|
||||
id="path4351-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 82.78126,29.998237 0.0156,1.4063 c -3.02668,-0.2402 -0.33008,3.6507 -2.48438,4.5781 2.18694,1.0938 -0.49191,4.90688 2.45313,4.57808 l 0.0156,1.4219 c -5.70828,0.559 -1.03264,-5.10038 -4.70313,-5.26558 l 0,-1.4063 c 3.61303,-0.027 -1.11893,-5.7071 4.70313,-5.3125 z"
|
||||
id="path4351-9-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
|
||||
id="rect3754-65"
|
||||
width="16"
|
||||
height="16"
|
||||
x="100"
|
||||
y="27.99992" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 103.719,29.671937 0,12.71878 3.03125,0 0,-1.5313 -1.34375,0 0,-9.62498 1.375,0 0,-1.5625 z"
|
||||
id="path2987-8"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 112.2185,29.671937 0,12.71878 -3.03125,0 0,-1.5313 1.34375,0 0,-9.62498 -1.375,0 0,-1.5625 z"
|
||||
id="path2987-1-9"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
|
||||
id="rect3754-92"
|
||||
width="16"
|
||||
height="16"
|
||||
x="124"
|
||||
y="27.99992" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 126.2824,41.602917 1.78957,0 1.14143,-2.86408 5.65364,0 1.14856,2.86408 1.76565,0 -4.78687,-11.16108 -1.91902,0 z"
|
||||
id="path3780-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
|
||||
d="m 129.72704,37.478837 4.60852,0.01 -2.30426,-5.5498 z"
|
||||
id="path3782-2"
|
||||
inkscape:connector-curvature="0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
|
||||
id="rect3754-47"
|
||||
width="16"
|
||||
height="16"
|
||||
x="148"
|
||||
y="27.99992" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 156.47656,29.891737 0,2.1797 0.46093,2.3984 1.82813,0 0.39844,-2.3984 0,-2.1797 z"
|
||||
id="path5008-2-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 152.51562,29.890637 0,2.1797 0.46094,2.3984 1.82812,0 0.39844,-2.3984 0,-2.1797 z"
|
||||
id="path5008-2-8-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<rect
|
||||
id="svg_1-7-2"
|
||||
height="1.9999961"
|
||||
width="11.999996"
|
||||
y="64"
|
||||
x="54"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="svg_1-7-2-2"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="52"
|
||||
x="80.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="85.000008"
|
||||
y="52"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4561" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="80.000008"
|
||||
y="58"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4563" />
|
||||
<rect
|
||||
id="rect4565"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="58"
|
||||
x="85.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4567"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="64"
|
||||
x="80.000008"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="85.000008"
|
||||
y="64"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4569" />
|
||||
<circle
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4571"
|
||||
cx="110.06081"
|
||||
cy="57.939209"
|
||||
r="4.7438836" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="116.64566"
|
||||
y="-31.79752"
|
||||
width="4.229713"
|
||||
height="6.4053884"
|
||||
id="rect4563-2"
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
|
||||
<path
|
||||
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 125,56 138.77027,56.095 132,64 Z"
|
||||
id="path4613"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4615"
|
||||
d="M 149,64 162.77027,63.905 156,56 Z"
|
||||
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="54"
|
||||
y="53"
|
||||
width="11.999996"
|
||||
height="1.9999961"
|
||||
id="rect4638" />
|
||||
<rect
|
||||
id="svg_1-7-2-24"
|
||||
height="1.9999957"
|
||||
width="12.99999"
|
||||
y="-56"
|
||||
x="53"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
transform="matrix(0,1,-1,0,0,0)" />
|
||||
<rect
|
||||
transform="matrix(0,1,-1,0,0,0)"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
|
||||
x="53"
|
||||
y="-66"
|
||||
width="12.99999"
|
||||
height="1.9999957"
|
||||
id="rect4657" />
|
||||
<rect
|
||||
id="rect4659"
|
||||
height="0.99999291"
|
||||
width="11.999999"
|
||||
y="57"
|
||||
x="54"
|
||||
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="54"
|
||||
y="88.000122"
|
||||
width="11.999996"
|
||||
height="1.9999961"
|
||||
id="rect4661" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="80.000008"
|
||||
y="76.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4663" />
|
||||
<rect
|
||||
id="rect4665"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="76.000122"
|
||||
x="85.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
id="rect4667"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="82.000122"
|
||||
x="80.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="85.000008"
|
||||
y="82.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4669" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="80.000008"
|
||||
y="88.000122"
|
||||
width="2.9999907"
|
||||
height="2.9999905"
|
||||
id="rect4671" />
|
||||
<rect
|
||||
id="rect4673"
|
||||
height="2.9999905"
|
||||
width="2.9999907"
|
||||
y="88.000122"
|
||||
x="85.000008"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<circle
|
||||
r="4.7438836"
|
||||
cy="81.939331"
|
||||
cx="110.06081"
|
||||
id="circle4675"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
|
||||
id="rect4677"
|
||||
height="6.4053884"
|
||||
width="4.229713"
|
||||
y="-14.826816"
|
||||
x="133.6163"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4679"
|
||||
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
|
||||
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
|
||||
id="path4681"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<rect
|
||||
id="rect4683"
|
||||
height="1.9999961"
|
||||
width="11.999996"
|
||||
y="77.000122"
|
||||
x="54"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="matrix(0,1,-1,0,0,0)"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="77.000122"
|
||||
y="-56"
|
||||
width="12.99999"
|
||||
height="1.9999957"
|
||||
id="rect4685" />
|
||||
<rect
|
||||
id="rect4687"
|
||||
height="1.9999957"
|
||||
width="12.99999"
|
||||
y="-66"
|
||||
x="77.000122"
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
transform="matrix(0,1,-1,0,0,0)" />
|
||||
<rect
|
||||
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
|
||||
x="54"
|
||||
y="81.000122"
|
||||
width="11.999999"
|
||||
height="0.99999291"
|
||||
id="rect4689" />
|
||||
<rect
|
||||
id="rect4761-1"
|
||||
height="1.9999945"
|
||||
width="15.99999"
|
||||
y="101"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-0"
|
||||
height="1.9999945"
|
||||
width="15.99999"
|
||||
y="105"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-7"
|
||||
height="1.9999945"
|
||||
width="9"
|
||||
y="109"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1"
|
||||
height="1.9999945"
|
||||
width="12"
|
||||
y="125"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4"
|
||||
height="1.9999945"
|
||||
width="10"
|
||||
y="137"
|
||||
x="76.000008"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4-4"
|
||||
height="1.9999945"
|
||||
width="10"
|
||||
y="129"
|
||||
x="82"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<rect
|
||||
id="rect4761-1-1-4-4-3"
|
||||
height="1.9999945"
|
||||
width="9"
|
||||
y="133"
|
||||
x="82"
|
||||
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
|
||||
id="path4138" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
|
||||
id="path4138-1" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
|
||||
id="path3055-0-77" />
|
||||
<path
|
||||
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.9850574,108.015 14.0298856,-0.03"
|
||||
id="path5244-5-0-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 4.9849874,132.015 14.0298866,-0.03"
|
||||
id="path5244-5-0-5-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
|
||||
id="path4138-12" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
|
||||
id="path4138-1-3" />
|
||||
<path
|
||||
id="path6191"
|
||||
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
|
||||
id="path6193" />
|
||||
<path
|
||||
id="path6195"
|
||||
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
|
||||
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4500"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:cy="60.073242"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
|
||||
inkscape:transform-center-x="-1.2779026" />
|
||||
<path
|
||||
inkscape:transform-center-x="1.277902"
|
||||
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:cy="60.073242"
|
||||
sodipodi:cx="-36.611614"
|
||||
sodipodi:sides="3"
|
||||
id="path4502"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:type="star"
|
||||
transform="scale(-1,1)" />
|
||||
<path
|
||||
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="false"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:cy="60.073212"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:sides="3"
|
||||
id="path4504"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
sodipodi:type="star"
|
||||
transform="matrix(0,1,-1,0,72.0074,71.7877)"
|
||||
inkscape:transform-center-y="1.2779029" />
|
||||
<path
|
||||
inkscape:transform-center-y="-1.2779026"
|
||||
transform="matrix(0,-1,-1,0,96,96)"
|
||||
sodipodi:type="star"
|
||||
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="path4506"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="11.55581"
|
||||
sodipodi:cy="60.073212"
|
||||
sodipodi:r1="5.1116104"
|
||||
sodipodi:r2="2.5558052"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4615-5"
|
||||
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
|
||||
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179,55 0,6 2,0 0,-6"
|
||||
id="path4300"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 179,62 0,2 2,0 0,-2"
|
||||
id="path4300-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 35 KiB |
2
public/css/jquery.datetimepicker.min.css
vendored
Normal file
2
public/css/jquery.datetimepicker.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/jquery.datetimepicker.min.css.map
Normal file
1
public/css/jquery.datetimepicker.min.css.map
Normal file
File diff suppressed because one or more lines are too long
1
public/css/jsoneditor.min.css.map
Normal file
1
public/css/jsoneditor.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
public/css/lightbox.min.css
vendored
Normal file
2
public/css/lightbox.min.css
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
body:after{content:url(../images/close.png) url(../images/loading.gif) url(../images/prev.png) url(../images/next.png);display:none}body.lb-disable-scrolling{overflow:hidden}.lightboxOverlay{position:absolute;top:0;left:0;z-index:9999;background-color:#000;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);opacity:.8;display:none}.lightbox{position:absolute;left:0;width:100%;z-index:10000;text-align:center;line-height:0;font-weight:400}.lightbox .lb-image{display:block;height:auto;max-width:inherit;border-radius:3px}.lightbox a img{border:none}.lb-outerContainer{position:relative;background-color:#fff;*zoom:1;width:250px;height:250px;margin:0 auto;border-radius:4px}.lb-outerContainer:after{content:"";display:table;clear:both}.lb-container{padding:4px}.lb-loader{position:absolute;top:43%;left:0;height:25%;width:100%;text-align:center;line-height:0}.lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background:url(../images/loading.gif) no-repeat}.lb-nav{position:absolute;top:0;left:0;height:100%;width:100%;z-index:10}.lb-container>.nav{left:0}.lb-nav a{outline:none;background-image:url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')}.lb-next,.lb-prev{height:100%;cursor:pointer;display:block}.lb-nav a.lb-prev{width:34%;left:0;float:left;background:url(../images/prev.png) left 48% no-repeat;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-prev:hover{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.lb-nav a.lb-next{width:64%;right:0;float:right;background:url(../images/next.png) right 48% no-repeat;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=0);opacity:0;-webkit-transition:opacity .6s;transition:opacity .6s}.lb-nav a.lb-next:hover{filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}.lb-dataContainer{margin:0 auto;padding-top:5px;*zoom:1;width:100%;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.lb-dataContainer:after{content:"";display:table;clear:both}.lb-data{padding:0 4px;color:#ccc}.lb-data .lb-details{width:85%;float:left;text-align:left;line-height:1.1em}.lb-data .lb-caption{font-size:13px;font-weight:700;line-height:1em}.lb-data .lb-number{display:block;clear:left;padding-bottom:1em;font-size:12px;color:#999}.lb-data .lb-close{display:block;float:right;width:30px;height:30px;background:url(../images/close.png) 100% 0 no-repeat;text-align:right;outline:none;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=70);opacity:.7;-webkit-transition:opacity .2s;transition:opacity .2s}.lb-data .lb-close:hover{cursor:pointer;filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);opacity:1}
|
||||
/*# sourceMappingURL=lightbox.min.css.map */
|
1
public/css/lightbox.min.css.map
Normal file
1
public/css/lightbox.min.css.map
Normal file
File diff suppressed because one or more lines are too long
6
public/css/quill.snow.min.css
vendored
Normal file
6
public/css/quill.snow.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/quill.snow.min.css.map
Normal file
1
public/css/quill.snow.min.css.map
Normal file
File diff suppressed because one or more lines are too long
2
public/css/style.min.css
vendored
Normal file
2
public/css/style.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/css/style.min.css.map
Normal file
1
public/css/style.min.css.map
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user