Compare commits

...

27 Commits

Author SHA1 Message Date
snipe 43cdace9de Merge remote-tracking branch 'origin/develop' 2015-02-17 19:18:10 -08:00
snipe a04af4aead Bumped version number 2015-02-17 19:17:53 -08:00
snipe e7eec42ab8 Merge pull request #532 from uberbrady/depreciation_refactor
Depreciation refactor
2015-02-17 18:55:52 -08:00
Brady Wetherington 063e5c407c Fixed the depreciation report, fixes to calculate current depreciated
value (which were only used there). Additional fixes and refactoring
around Depreciable, in terms of how assets get depreciation via models,
and licenses get depreciation directly.
2015-02-17 18:51:13 -08:00
Brady Wetherington 3ba02b65fb Oops - Assets get their Depreciation from their *model* - wheras
Licenses have a Depreciation directly associated with them. So I
pulled the Depreciation relationship out of Depreciable so that both
Assets and Licenses could pull their depreciations in their associated
ways. I could've done this with an inheritance call, but that seems
a bit much (and unnecessarily confusing).
2015-02-17 17:56:59 -08:00
Brady Wetherington 88dc0700f0 Make date functions work; create negative intervals for depreciation,
Also renamed "months_until_depreciation" to "time_until_depreciation"
And renamed Depreciatable to Depreciable (which is an actual word in
English.) Also a cleanup/consistency-enforcement for interval display.
2015-02-17 17:40:16 -08:00
Brady Wetherington 899e2bc9b6 Not convinved this filename is right or anything, but the shared depreciation code is here 2015-02-17 17:40:16 -08:00
Brady Wetherington 1e4071b51d First stab at cleaning up Depreciation
Conflicts:
	app/models/Asset.php

It looks like the same time I pulled depreciation out of the
Asset class, uploads were being added in. It doesn't look
like a conflict to me, but git couldn't figure it out. Oh Well.
2015-02-17 17:39:39 -08:00
snipe 38961298ed Fixes #439 - loads javascript and CSS locally 2015-02-17 15:29:57 -08:00
snipe ea6a6d098a Fixes #440 - removed unique constraint on serial 2015-02-17 14:15:22 -08:00
snipe 1f0f9c2441 Merge remote-tracking branch 'origin/develop' 2015-02-16 20:50:41 -08:00
snipe d4fbea3571 Merge remote-tracking branch 'origin/develop' 2015-02-16 20:49:55 -08:00
snipe b32d74de57 Fixed seeder with duplicate ID 2015-02-16 19:56:11 -08:00
snipe 4e4144ea74 Fixed blade reference 2015-02-16 19:43:22 -08:00
snipe 7b331b26d3 Language string for nothing updated on bulk update 2015-02-16 18:27:27 -08:00
snipe e02bea4275 Fixes #457 - added bulk options to hardware 2015-02-16 18:21:29 -08:00
snipe 24f5cdc743 Fixes #523 - added file uploads to assets 2015-02-16 13:49:51 -08:00
snipe 08ee02d0cd Fixes #525 - added serial to asset model UI 2015-02-16 13:12:57 -08:00
snipe ec1ab6913e Merged layout blades for unified nav 2015-02-16 12:55:32 -08:00
snipe f40bb7b8b3 Fixes #520 postal code requirement 2015-02-13 11:40:28 -08:00
snipe 17258b73a1 Fixes #520 - state no longer required 2015-02-13 11:37:47 -08:00
snipe 4a5007264e Fixed mac address not showing 2015-02-12 21:34:20 -08:00
snipe bd01b11f4f Merge pull request #519 from madd15/patch-2
Fix #517 - User Requestable Assets
2015-02-12 13:21:48 -08:00
madd15 064c0211db Fix #517 - User Requestable Assets 2015-02-13 07:50:47 +10:30
snipe 4cb931a93b Merge remote-tracking branch 'origin/develop' 2015-02-12 12:50:15 -08:00
snipe 3df8243d80 Updated composer to include mockery 2015-02-12 12:49:57 -08:00
snipe f57c61dd4d Possible fix for #518 - license count issue 2015-02-12 12:25:22 -08:00
48 changed files with 15628 additions and 471 deletions
@@ -36,7 +36,7 @@ class ViewAssetsController extends AuthorizedController
public function getRequestableIndex() {
$assets = Asset::with('model','defaultLoc')->Hardware()->Requestable()->get();
$assets = Asset::with('model','defaultLoc')->Hardware()->RequestableAssets()->get();
return View::make('frontend/account/requestable-assets', compact('user','assets'));
}
+226 -2
View File
@@ -306,7 +306,7 @@ class AssetsController extends AdminController
$asset->supplier_id = e(Input::get('supplier_id'));
}
if (e(Input::get('requestable')) == '') {
if (e(Input::get('requestable')) == '') {
$asset->requestable = 0;
} else {
$asset->requestable = e(Input::get('requestable'));
@@ -604,7 +604,7 @@ class AssetsController extends AdminController
// Grab the dropdown list of status
$statuslabel_list = Statuslabel::lists('name', 'id');
$location_list = array('' => '') + Location::lists('name', 'id');
$location_list = array('' => '') + Location::lists('name', 'id');
// get depreciation list
$depreciation_list = array('' => '') + Depreciation::lists('name', 'id');
@@ -641,4 +641,228 @@ class AssetsController extends AdminController
}
}
/**
* Upload the file to the server
*
* @param int $assetId
* @return View
**/
public function postUpload($assetID = null)
{
$asset = Asset::find($assetID);
// the asset is valid
$destinationPath = app_path().'/private_uploads';
if (isset($asset->id)) {
if (Input::hasFile('assetfile')) {
foreach(Input::file('assetfile') as $file) {
$rules = array(
'assetfile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt|max:2000'
);
$validator = Validator::make(array('assetfile'=> $file), $rules);
if($validator->passes()){
$extension = $file->getClientOriginalExtension();
$filename = 'hardware-'.$asset->id.'-'.str_random(8);
$filename .= '-'.Str::slug($file->getClientOriginalName()).'.'.$extension;
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->asset_type = 'hardware';
$logaction->user_id = Sentry::getUser()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = NULL;
$logaction->created_at = date("Y-m-d h:i:s");
$logaction->filename = $filename;
$log = $logaction->logaction('uploaded');
} else {
return Redirect::back()->with('error', Lang::get('admin/hardware/message.upload.invalidfiles'));
}
}
if ($upload_success) {
return Redirect::back()->with('success', Lang::get('admin/hardware/message.upload.success'));
} else {
return Redirect::back()->with('success', Lang::get('admin/hardware/message.upload.error'));
}
} else {
return Redirect::back()->with('success', Lang::get('admin/hardware/message.upload.nofiles'));
}
} else {
// Prepare the error message
$error = Lang::get('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return Redirect::route('hardware')->with('error', $error);
}
}
/**
* Delete the associated file
*
* @param int $assetId
* @return View
**/
public function getDeleteFile($assetID = null, $fileId = null)
{
$asset = Asset::find($assetID);
$destinationPath = app_path().'/private_uploads';
// the asset is valid
if (isset($asset->id)) {
$log = Actionlog::find($fileId);
$full_filename = $destinationPath.'/'.$log->filename;
if (file_exists($full_filename)) {
unlink($destinationPath.'/'.$log->filename);
}
$log->delete();
return Redirect::back()->with('success', Lang::get('admin/hardware/message.deletefile.success'));
} else {
// Prepare the error message
$error = Lang::get('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return Redirect::route('hardware')->with('error', $error);
}
}
/**
* Display/download the uploaded file
*
* @param int $assetId
* @return View
**/
public function displayFile($assetID = null, $fileId = null)
{
$asset = Asset::find($assetID);
// the asset is valid
if (isset($asset->id)) {
$log = Actionlog::find($fileId);
$file = $log->get_src();
return Response::download($file);
} else {
// Prepare the error message
$error = Lang::get('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return Redirect::route('hardware')->with('error', $error);
}
}
/**
* Display bulk edit screen
*
* @return View
**/
public function postBulkEdit($assets = null)
{
if (Input::has('edit_asset')) {
$assets = Input::get('edit_asset');
$supplier_list = array('' => '') + Supplier::orderBy('name', 'asc')->lists('name', 'id');
$statuslabel_list = array('' => '') + Statuslabel::lists('name', 'id');
$location_list = array('' => '') + Location::lists('name', 'id');
}
return View::make('backend/hardware/bulk')->with('assets',$assets)->with('supplier_list',$supplier_list)->with('statuslabel_list',$statuslabel_list)->with('location_list',$location_list);
}
/**
* Save bulk edits
*
* @return View
**/
public function postBulkSave($assets = null)
{
if (Input::has('bulk_edit')) {
$assets = Input::get('bulk_edit');
if ( (Input::has('purchase_date')) || (Input::has('rtd_location_id')) || (Input::has('status_id')) ) {
foreach ($assets as $key => $value) {
$update_array = array();
if (Input::has('purchase_date')) {
$update_array['purchase_date'] = e(Input::get('purchase_date'));
}
if (Input::has('rtd_location_id')) {
$update_array['rtd_location_id'] = e(Input::get('rtd_location_id'));
}
if (Input::has('status_id')) {
$update_array['status_id'] = e(Input::get('status_id'));
}
if (DB::table('assets')
->where('id', $key)
->update($update_array)) {
$logaction = new Actionlog();
$logaction->asset_id = $key;
$logaction->asset_type = 'hardware';
$logaction->created_at = date("Y-m-d h:i:s");
if (Input::has('rtd_location_id')) {
$logaction->location_id = e(Input::get('rtd_location_id'));
}
$logaction->user_id = Sentry::getUser()->id;
$log = $logaction->logaction('update');
}
} // endforeach
return Redirect::to("hardware")->with('success', Lang::get('admin/hardware/message.update.success'));
// no values given, nothing to update
} else {
return Redirect::to("hardware")->with('info',Lang::get('admin/hardware/message.update.nothing_updated'));
}
} // endif
return Redirect::to("hardware");
}
}
+3 -3
View File
@@ -369,8 +369,8 @@ class LicensesController extends AdminController
// Delete the license and the associated license seats
DB::table('license_seats')
->where('id', $asset->id)
->update(array('assigned_to' => NULL));
->where('id', $license->id)
->update(array('assigned_to' => NULL,'asset_id' => NULL));
$licenseseats = $license->licenseseats();
$licenseseats->delete();
@@ -578,7 +578,7 @@ class LicensesController extends AdminController
$logaction->checkedout_to = $licenseseat->assigned_to;
// Update the asset data
$licenseseat->assigned_to = '0';
$licenseseat->assigned_to = NULL;
$licenseseat->asset_id = NULL;
// Was the asset updated?
@@ -86,6 +86,7 @@ class SettingsController extends AdminController
$setting->per_page = e(Input::get('per_page'));
$setting->qr_code = e(Input::get('qr_code', '0'));
$setting->display_eol = e(Input::get('display_eol', '0'));
$setting->load_remote = e(Input::get('load_remote', '0'));
$setting->qr_text = e(Input::get('qr_text'));
$setting->auto_increment_prefix = e(Input::get('auto_increment_prefix'));
$setting->auto_increment_assets = e(Input::get('auto_increment_assets', '0'));
@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddLocalonlyToSettings extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table('settings', function ($table) {
$table->boolean('load_remote')->default(1);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::table('settings', function ($table) {
$table->dropColumn('load_remote');
});
}
}
+2 -2
View File
@@ -175,8 +175,8 @@ class AssetsSeeder extends Seeder
$asset[] = array(
'name' => 'Broke-Ass Laptop',
'asset_tag' => 'NNY67567775',
'name' => 'Broken Laptop',
'asset_tag' => 'NNY6756756775',
'model_id' => 2,
'serial' => 'WS89080890',
'purchase_date' => '2012-01-02',
+3
View File
@@ -2,6 +2,9 @@
return array(
'bulk_update' => 'Bulk Update Assets',
'bulk_update_help' => 'This form allows you to update multiple assets at once. Only fill in the fields you need to change. Any fields left blank will remain unchanged. ',
'bulk_update_warn' => 'You are about to edit the properties of :asset_count assets.',
'checkedout_to' => 'Checked Out To',
'checkout_to' => 'Checkout to',
'cost' => 'Purchase Cost',
+16 -2
View File
@@ -13,14 +13,28 @@ return array(
),
'update' => array(
'error' => 'Asset was not updated, please try again',
'success' => 'Asset updated successfully.'
'error' => 'Asset was not updated, please try again',
'success' => 'Asset updated successfully.',
'nothing_updated' => 'No fields were selected, so nothing was updated.',
),
'restore' => array(
'error' => 'Asset was not restored, please try again',
'success' => 'Asset restored successfully.'
),
'deletefile' => array(
'error' => 'File not deleted. Please try again.',
'success' => 'File successfully deleted.',
),
'upload' => array(
'error' => 'File(s) not uploaded. Please try again.',
'success' => 'File(s) successfully uploaded.',
'nofiles' => 'You did not select any files for upload',
'invalidfiles' => 'One or more of your files is too large or is a filetype that is not allowed. Allowed filetypes are png, gif, jpg, doc, docx, pdf, and txt.',
),
'delete' => array(
'confirm' => 'Are you sure you wish to delete this asset?',
+1
View File
@@ -10,6 +10,7 @@ return array(
'display_qr' => 'Display QR Codes',
'info' => 'These settings let you customize certain aspects of your installation.',
'laravel' => 'Laravel Version',
'load_remote' => 'This Snipe-IT install can load scripts from the outside world.',
'per_page' => 'Results Per Page',
'php' => 'PHP Version',
'php_gd_info' => 'You must install php-gd to display QR codes, see install instructions.',
+3 -2
View File
@@ -37,6 +37,7 @@ return array(
'deleted' => 'Deleted',
'deployed' => 'Deployed',
'depreciation_report' => 'Depreciation Report',
'download' => 'Download',
'depreciation' => 'Depreciation',
'editprofile' => 'Edit Your Profile',
'eol' => 'EOL',
@@ -48,8 +49,8 @@ return array(
'gravatar_email' => 'Gravatar Email Address',
'history_for' => 'History for',
'id' => 'ID',
'image_delete' => 'Delete Image',
'image_upload' => 'Upload Image',
'image_delete' => 'Delete Image',
'image_upload' => 'Upload Image',
'last_name' => 'Last Name',
'license' => 'License',
'license_report' => 'License Report',
+31 -45
View File
@@ -1,6 +1,6 @@
<?php
class Asset extends Elegant
class Asset extends Depreciable
{
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
@@ -15,29 +15,36 @@ class Asset extends Elegant
'notes' => 'alpha_space',
'pysical' => 'integer',
'supplier_id' => 'integer',
//'asset_tag' => 'required|alpha_space|min:3|max:255|unique:assets,asset_tag,{id},deleted_at,NULL',
//'email' => 'required|email|unique:users,email,NULL,id,deleted_at,NULL',
//'asset_tag' => 'required|alpha_space|min:2|max:255|unique:assets,asset_tag,deleted_at,NULL',
'asset_tag' => 'required|alpha_space|min:3|max:255|unique:assets,asset_tag,{id}',
'serial' => 'required|alpha_dash|min:3|max:255|unique:assets,serial,{id}',
//'serial' => 'required|alpha_dash|min:3|max:255|unique:assets,serial,{id}',
'status' => 'integer'
);
/**
* Handle depreciation
*/
public function depreciate()
public function depreciation()
{
return $this->getCurrentValue(
Model::find($this->model_id)->depreciation_id,
$this->purchase_cost,
$this->purchase_date
);
return $this->model->belongsTo('Depreciation','depreciation_id');
}
public function get_depreciation()
{
return $this->model->depreciation;
}
/**
* Get uploads for this asset
*/
public function uploads()
{
return $this->hasMany('Actionlog','asset_id')
->where('asset_type', '=', 'hardware')
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
public function assigneduser()
{
return $this->belongsTo('User', 'assigned_to');
return $this->belongsTo('User', 'assigned_to')->withTrashed();
}
/**
@@ -120,33 +127,6 @@ class Asset extends Elegant
return date_format($date, 'Y-m-d');
}
public function months_until_depreciated()
{
$today = date("Y-m-d");
// @link http://www.php.net/manual/en/class.datetime.php
$d1 = new DateTime($today);
$d2 = new DateTime($this->depreciated_date());
// @link http://www.php.net/manual/en/class.dateinterval.php
$interval = $d1->diff($d2);
return $interval;
}
public function depreciated_date()
{
$date = date_create($this->purchase_date);
date_add($date, date_interval_create_from_date_string($this->depreciation->months.' months'));
return date_format($date, 'Y-m-d');
}
public function depreciation()
{
return $this->model->belongsTo('Depreciation','depreciation_id');
}
public function model()
{
return $this->belongsTo('Model','model_id');
@@ -155,13 +135,13 @@ class Asset extends Elegant
/**
* Get the license seat information
**/
public function licenses()
public function licenses()
{
return $this->belongsToMany('License', 'license_seats', 'asset_id', 'license_id');
}
public function licenseseats()
public function licenseseats()
{
return $this->hasMany('LicenseSeat', 'asset_id');
}
@@ -198,9 +178,15 @@ class Asset extends Elegant
/**
* Get total assets
*/
public static function autoincrement_asset()
public static function autoincrement_asset()
{
$settings = Setting::getSettings();
if (isset($asset_tag->id)) {
$asset_id = $asset_tag->id;
} else {
$asset_id = 1;
}
if ($settings->auto_increment_assets == '1') {
$asset_tag = DB::table('assets')
->where('physical', '=', '1')
+81
View File
@@ -0,0 +1,81 @@
<?php
class Depreciable extends Elegant
{
/**
* Depreciation Relation, and associated helper methods
*/
//REQUIRES a purchase_date field
// and a purchase_cost field
//REQUIRES a get_depreciation method,
//which will return the deprecation.
//this is needed because assets get
//their depreciation from a model,
//whereas licenses have deprecations
//directly associated with them.
//assets will override the following
//two methods in order to inherit from
//their model instead of directly (like
//here)
public function depreciation()
{
return $this->belongsTo('Depreciation','depreciation_id');
}
public function get_depreciation()
{
return $this->depreciation;
}
/**
* @param $purchase_cost
* @param $purchase_date1
* @return float|int
*/
public function getDepreciatedValue()
{
if (!$this->get_depreciation()) { // will never happen
return $this->purchase_cost;
}
if ($this->get_depreciation()->months <= 0) {
return $this->purchase_cost;
}
// fraction of value left
$months_remaining = $this->time_until_depreciated()->m + $this->time_until_depreciated()->y; //UGlY
$current_value = round(($months_remaining/ $this->get_depreciation()->months) * $this->purchase_cost, 2);
if ($current_value < 0) {
$current_value = 0;
}
return $current_value;
}
public function time_until_depreciated()
{
// @link http://www.php.net/manual/en/class.datetime.php
$d1 = new DateTime();
$d2 = $this->depreciated_date();
// @link http://www.php.net/manual/en/class.dateinterval.php
$interval = $d1->diff($d2);
if(!$interval->invert) {
return $interval;
} else {
return new DateInterval("PT0S"); //null interval (zero seconds from now)
}
}
public function depreciated_date()
{
$date = date_create($this->purchase_date);
date_add($date, date_interval_create_from_date_string($this->get_depreciation()->months . ' months'));
return $date; //date_format($date, 'Y-m-d'); //don't bake-in format, for internationalization
}
}
+5
View File
@@ -12,4 +12,9 @@ class Depreciation extends Elegant
{
return $this->hasMany('Model', 'depreciation_id')->count();
}
public function has_licenses()
{
return $this->hasMany('License','depreciation_id')->count();
}
}
-32
View File
@@ -30,36 +30,4 @@ class Elegant extends Eloquent
{
return str_replace("{id}", $id, $this->rules);
}
/**
* @param $depreciation_id
* @param $purchase_cost
* @param $purchase_date1
* @return float|int
*/
protected function getCurrentValue($depreciation_id, $purchase_cost, $purchase_date1)
{
if (!$depreciation_id) {
return $purchase_cost;
}
$depreciation_term = Depreciation::find($depreciation_id)->months;
if ($depreciation_term <= 0) {
return $purchase_cost;
}
$purchase_date = strtotime($purchase_date1);
$todaymonthnumber = date("Y") * 12 + (date("m") - 1); //calculate the month number for today as YEAR*12 + (months-1) - number of months since January year 0
$purchasemonthnumber = date("Y", $purchase_date) * 12 + (date("m", $purchase_date) - 1); //purchase date calculated similarly
$diff_months = $todaymonthnumber - $purchasemonthnumber;
// fraction of value left
$current_value = round((($depreciation_term - $diff_months) / ($depreciation_term)) * $purchase_cost, 2);
if ($current_value < 0) {
$current_value = 0;
}
return $current_value;
}
}
+2 -42
View File
@@ -1,11 +1,11 @@
<?php
class License extends Elegant
class License extends Depreciable
{
use SoftDeletingTrait;
protected $dates = ['deleted_at'];
public $timestamps = true;
public $timestamps = true;
protected $guarded = 'id';
protected $table = 'licenses';
@@ -155,44 +155,4 @@ class License extends Elegant
{
return $this->belongsTo('Supplier','supplier_id');
}
/**
* Get depreciation class
*/
public function depreciation()
{
return $this->belongsTo('Depreciation','depreciation_id');
}
public function months_until_depreciated()
{
$today = date("Y-m-d");
// @link http://www.php.net/manual/en/class.datetime.php
$d1 = new DateTime($today);
$d2 = new DateTime($this->depreciated_date());
// @link http://www.php.net/manual/en/class.dateinterval.php
$interval = $d1->diff($d2);
return $interval;
}
public function depreciated_date()
{
$date = date_create($this->purchase_date);
date_add($date, date_interval_create_from_date_string($this->depreciation->months . ' months'));
return date_format($date, 'Y-m-d');
}
/**
* Handle depreciation
*/
public function depreciate()
{
return $this->getCurrentValue(
License::find($this->license_id)->depreciation_id,
$this->purchase_cost,
$this->purchase_date
);
}
}
+2 -2
View File
@@ -8,11 +8,11 @@ class Location extends Elegant
protected $rules = array(
'name' => 'required|alpha_space|min:3|max:255|unique:locations,name,{id}',
'city' => 'required|alpha_space|min:3|max:255',
'state' => 'required|alpha_space|min:2|max:32',
'state' => 'alpha_space|min:2|max:32',
'country' => 'required|alpha_space|min:2|max:2|max:2',
'address' => 'required|alpha_space|min:5|max:80',
'address2' => 'alpha_space|min:5|max:80',
'zip' => 'alpha_dash|min:3|max:10',
'zip' => 'alpha_space|min:3|max:10',
);
public function has_users()
+14 -1
View File
@@ -33,7 +33,6 @@ Route::group(array('prefix' => 'hardware', 'namespace' => 'Controllers\Admin', '
'uses' => 'AssetsController@getEdit')
);
Route::post('{assetId}/edit', 'AssetsController@postEdit');
Route::get('{assetId}/clone', array('as' => 'clone/hardware', 'uses' => 'AssetsController@getClone'));
Route::post('{assetId}/clone', 'AssetsController@postCreate');
Route::get('{assetId}/delete', array('as' => 'delete/hardware', 'uses' => 'AssetsController@getDelete'));
@@ -44,6 +43,20 @@ Route::group(array('prefix' => 'hardware', 'namespace' => 'Controllers\Admin', '
Route::get('{assetId}/view', array('as' => 'view/hardware', 'uses' => 'AssetsController@getView'));
Route::get('{assetId}/qr_code', array('as' => 'qr_code/hardware', 'uses' => 'AssetsController@getQrCode'));
Route::get('{assetId}/restore', array('as' => 'restore/hardware', 'uses' => 'AssetsController@getRestore'));
Route::post('{assetId}/upload', array('as' => 'upload/asset', 'uses' => 'AssetsController@postUpload'));
Route::get('{assetId}/deletefile/{fileId}', array('as' => 'delete/assetfile', 'uses' => 'AssetsController@getDeleteFile'));
Route::get('{assetId}/showfile/{fileId}', array('as' => 'show/assetfile', 'uses' => 'AssetsController@displayFile'));
Route::post('{assetId}/edit', 'AssetsController@postEdit');
Route::post('bulkedit',
array('as' => 'hardware/bulkedit',
'uses' => 'AssetsController@postBulkEdit'));
Route::post('bulksave',
array('as' => 'hardware/bulksave',
'uses' => 'AssetsController@postBulkSave'));
# Asset Model Management
+83
View File
@@ -0,0 +1,83 @@
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
@lang('admin/hardware/form.update') ::
@parent
@stop
{{-- Page content --}}
@section('content')
<div class="row header">
<div class="col-md-12">
<a href="{{ URL::previous() }}" class="btn-flat gray pull-right right"><i class="icon-circle-arrow-left icon-white"></i> @lang('general.back')</a>
<h3>
@lang('admin/hardware/form.bulk_update')
</h3>
</div>
</div>
<div class="row form-wrapper">
<!-- left column -->
<div class="col-md-12 column">
<p>@lang('admin/hardware/form.bulk_update_help')</p>
<p style="color: red"><strong><big>@lang('admin/hardware/form.bulk_update_warn', ['asset_count' => count($assets)])</big></strong></p>
<form class="form-horizontal" method="post" action="{{ route('hardware/bulksave') }}" autocomplete="off" role="form">
<!-- CSRF Token -->
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<!-- Purchase Date -->
<div class="form-group {{ $errors->has('purchase_date') ? ' has-error' : '' }}">
<label for="purchase_date" class="col-md-2 control-label">@lang('admin/hardware/form.date')</label>
<div class="input-group col-md-3">
<input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="Select Date" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date') }}}">
<span class="input-group-addon"><i class="icon-calendar"></i></span>
{{ $errors->first('purchase_date', '<span class="alert-msg"><i class="icon-remove-sign"></i> :message</span>') }}
</div>
</div>
<!-- Status -->
<div class="form-group {{ $errors->has('status_id') ? ' has-error' : '' }}">
<label for="status_id" class="col-md-2 control-label">@lang('admin/hardware/form.status') <i class='icon-asterisk'></i></label>
<div class="col-md-7">
{{ Form::select('status_id', $statuslabel_list , Input::old('status_id'), array('class'=>'select2', 'style'=>'width:350px')) }}
{{ $errors->first('status_id', '<span class="alert-msg"><i class="icon-remove-sign"></i> :message</span>') }}
</div>
</div>
<!-- Default Location -->
<div class="form-group {{ $errors->has('status_id') ? ' has-error' : '' }}">
<label for="status_id" class="col-md-2 control-label">@lang('admin/hardware/form.default_location')</label>
<div class="col-md-7">
{{ Form::select('rtd_location_id', $location_list , Input::old('rtd_location_id'), array('class'=>'select2', 'style'=>'width:350px')) }}
{{ $errors->first('status_id', '<span class="alert-msg"><i class="icon-remove-sign"></i> :message</span>') }}
</div>
</div>
@foreach ($assets as $key => $value)
<input type="hidden" name="bulk_edit[{{{ $key }}}]" value="1">
@endforeach
<!-- Form actions -->
<div class="form-group">
<label class="col-md-2 control-label"></label>
<div class="col-md-7">
<a class="btn btn-link" href="{{ URL::previous() }}">@lang('button.cancel')</a>
<button type="submit" class="btn btn-success"><i class="icon-ok icon-white"></i> @lang('general.save')</button>
</div>
</div>
</form>
</div>
</div>
@stop
+2 -1
View File
@@ -90,7 +90,8 @@
</div>
</div>
@if (isset($asset->model)) && ($asset->model->show_mac_address != 0)
@if ($asset->model && $asset->model->show_mac_address == '1')
<!-- MAC Address -->
<div class="form-group {{ $errors->has('mac_address') ? ' has-error' : '' }}">
<label for="mac_address" class="col-md-2 control-label">@lang('admin/hardware/form.mac_address')</label>
+37 -2
View File
@@ -42,39 +42,56 @@
<div class="row form-wrapper">
<?php $spanrows = 8; ?>
@if ($assets->count() > 0)
{{ Form::open([
'method' => 'POST',
'route' => ['hardware/bulkedit'],
'class' => 'form-horizontal' ]) }}
<div class="table-responsive">
<table id="example">
<thead>
<tr role="row">
<th class="col-md-1" bSortable="false"></th>
<th class="col-md-1" bSortable="true">@lang('admin/hardware/table.asset_tag')</th>
<th class="col-md-3" bSortable="true">@lang('admin/hardware/table.asset_model')</th>
@if (Setting::getSettings()->display_asset_name)
<th class="col-md-3" bSortable="true">@lang('general.name')</th>
<?php $spanrows++; ?>
@endif
<th class="col-md-2" bSortable="true">@lang('admin/hardware/table.serial')</th>
<th class="col-md-2" bSortable="true">@lang('general.status')</th>
<th class="col-md-2" bSortable="true">@lang('admin/hardware/table.location')</th>
@if (Input::get('Deployed') && Setting::getSettings()->display_checkout_date)
<th class="col-md-2" bSortable="true">@lang('admin/hardware/table.checkout_date')</th>
<?php $spanrows++; ?>
@endif
@if (Setting::getSettings()->display_eol)
<th class="col-md-2">@lang('admin/hardware/table.eol')</th>
<?php $spanrows++; ?>
@endif
<th class="col-md-1">@lang('admin/hardware/table.change')</th>
<th class="col-md-2 actions" bSortable="false">@lang('table.actions')</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="{{{ $spanrows }}}"><button class="btn btn-default" id="bulkEdit" disabled>Bulk Edit</button></td>
</tr>
</tfoot>
<tbody>
@foreach ($assets as $asset)
<tr>
<td><input type="checkbox" name="edit_asset[{{ $asset->id }}]" class="one_required"></td>
<td><a href="{{ route('view/hardware', $asset->id) }}">{{{ $asset->asset_tag }}}</a></td>
<td><a href="{{ route('view/model', $asset->model->id) }}">{{{ $asset->model->name }}}</a></td>
@@ -160,7 +177,25 @@
@endforeach
</tbody>
</table>
{{ Form::close() }}
</div>
<script>
$(function() {
$('input.one_required').change(function() {
var check_checked = $('input.one_required:checked').length;
console.warn(check_checked);
if (check_checked > 0) {
$('#bulkEdit').removeAttr('disabled');
}
else {
$('#bulkEdit').attr('disabled', 'disabled');
}
});
});
</script>
@else
<div class="col-md-9">
<div class="alert alert-info alert-block">
+108 -15
View File
@@ -119,13 +119,13 @@
@lang('admin/hardware/form.months')
)</div>
<div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/hardware/form.fully_depreciated'): </strong>
{{{ $asset->months_until_depreciated()->m }}}
@lang('admin/hardware/form.months')
@if ($asset->months_until_depreciated()->y > 0)
, {{{ $asset->months_until_depreciated()->y }}}
@lang('admin/hardware/form.years')
@if ($asset->time_until_depreciated()->y > 0)
{{{ $asset->time_until_depreciated()->y }}}
@lang('admin/hardware/form.years'),
@endif
({{{ $asset->depreciated_date() }}})
{{{ $asset->time_until_depreciated()->m }}}
@lang('admin/hardware/form.months')
({{{ $asset->depreciated_date()->format('Y-m-d') }}})
</div>
@endif
@@ -187,6 +187,60 @@
</div>
</div>
@endif
<div class="col-md-12">
<h6>@lang('general.file_uploads') [ <a href="#" data-toggle="modal" data-target="#uploadFileModal">@lang('button.add')</a> ]</h6>
<table class="table table-hover">
<thead>
<tr>
<th class="col-md-5">@lang('general.notes')</th>
<th class="col-md-5"><span class="line"></span>@lang('general.file_name')</th>
<th class="col-md-2"></th>
<th class="col-md-2"></th>
</tr>
</thead>
<tbody>
@if (count($asset->uploads) > 0)
@foreach ($asset->uploads as $file)
<tr>
<td>
@if ($file->note) {{{ $file->note }}}
@endif
</td>
<td>
{{{ $file->filename }}}
</td>
<td>
@if ($file->filename)
<a href="{{ route('show/assetfile', [$asset->id, $file->id]) }}" class="btn btn-default">@lang('general.download')</a>
@endif
</td>
<td>
<a class="btn delete-asset btn-danger" href="{{ route('delete/assetfile', [$asset->id, $file->id]) }}"><i class="icon-trash icon-white"></i></a>
</td>
</tr>
@endforeach
@else
<tr>
<td colspan="4">
@lang('general.no_results')
</td>
</tr>
@endif
</tbody>
</table>
</div>
<!-- checked out assets table -->
@@ -203,7 +257,7 @@
<tbody>
@if (count($asset->assetlog) > 0)
@foreach ($asset->assetlog as $log)
@if ((isset($log->checkedout_to)) && ($log->checkedout_to!=0))
<tr>
<td>{{{ $log->created_at }}}</td>
<td>
@@ -215,13 +269,13 @@
<td>
@if ((isset($log->checkedout_to)) && ($log->checkedout_to!=0) && ($log->checkedout_to!=''))
@if ($log->userlog->deleted_at=='')
<a href="{{ route('view/user', $log->checkedout_to) }}">
{{{ $log->userlog->fullName() }}}
</a>
@else
<del>{{{ $log->userlog->fullName() }}}</del>
@endif
@if ($log->userlog->deleted_at=='')
<a href="{{ route('view/user', $log->checkedout_to) }}">
{{{ $log->userlog->fullName() }}}
</a>
@else
<del>{{{ $log->userlog->fullName() }}}</del>
@endif
@endif
</td>
@@ -230,7 +284,7 @@
@endif
</td>
</tr>
@endif
@endforeach
@endif
<tr>
@@ -341,4 +395,43 @@
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="uploadFileModal" tabindex="-1" role="dialog" aria-labelledby="uploadFileModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="uploadFileModalLabel">Upload File</h4>
</div>
{{ Form::open([
'method' => 'POST',
'route' => ['upload/asset', $asset->id],
'files' => true, 'class' => 'form-horizontal' ]) }}
<div class="modal-body">
<p>Allowed filetypes are png, gif, jpg, doc, docx, pdf, and txt.</p>
<div class="form-group col-md-12">
<div class="input-group col-md-12">
<input class="col-md-12 form-control" type="text" name="notes" id="notes" placeholder="Notes">
</div>
</div>
<div class="form-group col-md-12">
<div class="input-group col-md-12">
{{ Form::file('assetfile[]', ['multiple' => 'multiple']) }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">@lang('button.cancel')</button>
<button type="submit" class="btn btn-primary">@lang('button.upload')</button>
</div>
{{ Form::close() }}
</div>
</div>
</div>
@stop
+12 -7
View File
@@ -41,14 +41,14 @@
<link rel="stylesheet" href="{{ asset('assets/css/compiled/user-profile.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/compiled/form-showcase.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/lib/jquery.dataTables.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="//cdn.datatables.net/responsive/1.0.2/css/dataTables.responsive.css" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/compiled/dataTables.responsive.css') }}" type="text/css" media="screen" />
<!-- global header javascripts -->
<script src="//code.jquery.com/jquery-latest.js"></script>
<script src="//cdn.datatables.net/1.10.3/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/responsive/1.0.2/js/dataTables.responsive.js"></script>
<script src="{{ asset('assets/js/jquery-latest.js') }}"></script>
<script src="{{ asset('assets/js/jquery.dataTables.min.js') }}"></script>
<script src="{{ asset('assets/js/dataTables.responsive.js') }}"></script>
<script>
window.snipeit = {
@@ -60,13 +60,15 @@
@if (Setting::getSettings()->load_remote=='1')
<!-- open sans font -->
<link href='//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
@endif
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<script src="{{ asset('assets/js/html5.js') }}"></script>
<![endif]-->
<style>
@section('styles')
@@ -285,6 +287,9 @@
</ul>
</li>
@endif
<li><a href="{{ route('requestable-assets') }}" {{{ (Request::is('view-requestable*') ? ' class="active"' : '') }}} >@lang('admin/hardware/general.requestable') </a></li>
</ul>
</div>
<!-- end sidebar -->
@@ -365,7 +370,7 @@
<a target="_blank" href="http://docs.snipeitapp.com/">Documentation</a> |
<a href="https://crowdin.com/project/snipe-it">Help Translate It! </a> |
<a target="_blank" href="https://github.com/snipe/snipe-it/issues?state=open">Report a Bug</a>
&nbsp; &nbsp; (v1.2.4)</p>
&nbsp; &nbsp; (v1.2.5)</p>
</div>
</div>
</div>
+7 -7
View File
@@ -73,18 +73,18 @@
<div class="col-md-6" style="padding-bottom: 5px">
<strong>@lang('admin/hardware/form.depreciates_on'): </strong>
{{{ $license->depreciated_date() }}}
{{{ $license->depreciated_date()->format("Y-m-d") }}}
</div>
<div class="col-md-6" style="padding-bottom: 5px">
<strong>@lang('admin/hardware/form.fully_depreciated'): </strong>
{{{ $license->months_until_depreciated()->m }}}
@if ($license->time_until_depreciated()->y > 0)
{{{ $license->time_until_depreciated()->y }}}
@lang('admin/hardware/form.years'),
@endif
{{{ $license->time_until_depreciated()->m }}}
@lang('admin/hardware/form.months')
@if ($license->months_until_depreciated()->y > 0)
, {{{ $license->months_until_depreciated()->y }}}
@lang('admin/hardware/form.years')
@endif
</div>
@endif
@@ -191,7 +191,7 @@
@else
<tr>
<td colspan="4">
No files uploaded
@lang('general.no_results')
</td>
</tr>
+1 -1
View File
@@ -86,7 +86,7 @@
<!-- City -->
<div class="form-group {{ $errors->has('state') ? ' has-error' : '' }}">
<label for="state" class="col-md-2 control-label">@lang('admin/locations/table.state')
<i class='icon-asterisk'></i></label>
</label>
<div class="col-md-12">
<div class="col-xs-2">
+9 -1
View File
@@ -44,7 +44,8 @@
<tr role="row">
<th class="col-md-3">@lang('general.name')</th>
<th class="col-md-3">@lang('general.asset_tag')</th>
<th class="col-md-3">@lang('general.user')</th>
<th class="col-md-3">@lang('admin/hardware/table.serial')</th>
<th class="col-md-3">@lang('general.user')</th>
<th class="col-md-2">@lang('table.actions')</th>
</tr>
</thead>
@@ -55,6 +56,13 @@
<td><a href="{{ route('view/hardware', $modelassets->id) }}">{{{ $modelassets->name }}}</a></td>
<td><a href="{{ route('view/hardware', $modelassets->id) }}">{{{ $modelassets->asset_tag }}}</a></td>
<td>
@if ($modelassets->serial)
{{{ $modelassets->serial }}}
@endif
</td>
<td>
@if ($modelassets->assigneduser)
<a href="{{ route('view/user', $modelassets->assigned_to) }}">
{{{ $modelassets->assigneduser->fullName() }}}
+9 -4
View File
@@ -85,10 +85,15 @@
@endif
</td>
<td>
@if ($asset->assigned_to != 0)
<a href="{{ route('view/user', $asset->assigned_to) }}">
{{{ $asset->assigneduser->fullName() }}}
</a>
@if ($asset->assigneduser)
@if ($asset->assigneduser->deleted_at!='')
<del>{{{ $asset->assigneduser->fullName() }}}</del>
@else
<a href="{{ route('view/user', $asset->assigned_to) }}">
{{{ $asset->assigneduser->fullName() }}}
</a>
@endif
@endif
</td>
<td>
@@ -45,19 +45,29 @@
@foreach ($assets as $asset)
<tr>
<td>{{{ $asset->asset_tag }}}</td>
<td>
@if ($asset->deleted_at!='')
<del>{{{ $asset->asset_tag }}}</del>
@else
{{{ $asset->asset_tag }}}
@endif
</td>
<td>{{{ $asset->model->name }}}</td>
@if (Setting::getSettings()->display_asset_name)
<td>{{{ $asset->name }}}</td>
@endif
<td>{{ $asset->serial }}</td>
<td>
@if (isset($asset->assigned_to))
@if ($asset->assigned_to != 0)
<a href="{{ route('view/user', $asset->assigned_to) }}">
@if ($asset->assigneduser)
@if ($asset->assigneduser->deleted_at!='')
<del>{{{ $asset->assigneduser->fullName() }}}</del>
@else
<a href="{{ route('view/user', $asset->assigned_to) }}">
{{{ $asset->assigneduser->fullName() }}}
</a>
@endif
@endif
@endif
</td>
<td>
@@ -79,9 +89,9 @@
<td class="align-right">@lang('general.currency')
{{{ number_format($asset->purchase_cost) }}}</td>
<td class="align-right">@lang('general.currency')
{{{ number_format($asset->depreciate()) }}}</td>
{{{ number_format($asset->getDepreciatedValue()) }}}</td>
<td class="align-right">@lang('general.currency')
-{{{ number_format(($asset->purchase_cost - $asset->depreciate())) }}}</td>
-{{{ number_format(($asset->purchase_cost - $asset->getDepreciatedValue())) }}}</td>
@else
<td></td>
<td></td>
@@ -86,6 +86,12 @@ padding: 0px 20px;
@lang('admin/settings/general.display_checkout_date')
</label>
</div>
<div class="checkbox">
<label>
{{ Form::checkbox('load_remote', '1', Input::old('load_remote', $setting->load_remote)) }}
@lang('admin/settings/general.load_remote')
</label>
</div>
<hr>
<div class="checkbox">
@@ -94,6 +100,9 @@ padding: 0px 20px;
@lang('admin/settings/general.auto_increment_assets')
</label>
</div>
<div class="form-group {{ $errors->has('auto_increment_prefix') ? 'error' : '' }}">
{{ Form::label('auto_increment_prefix', Lang::get('admin/settings/general.auto_increment_prefix')) }}
@@ -71,6 +71,16 @@
<td>@lang('general.no')</td>
@endif
</tr>
<tr>
<td>@lang('admin/settings/general.load_remote')</td>
@if ($setting->load_remote == 1)
<td>@lang('general.yes')</td>
@else
<td>@lang('general.no')</td>
@endif
</tr>
<tr>
<td>@lang('admin/settings/general.auto_increment_prefix')</td>
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
+1 -1
View File
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
@section('title0')
@lang('admin/hardware/general.requestable')
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
+1 -1
View File
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
+1 -1
View File
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page title --}}
@section('title')
+1 -1
View File
@@ -1,4 +1,4 @@
@extends('frontend/layouts/default')
@extends('backend/layouts/default')
{{-- Page content --}}
@section('content')
@@ -1,228 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Basic Page Needs
================================================== -->
<meta charset="utf-8" />
<title>
@section('title')
{{{ Setting::getSettings()->site_name }}}
@show
</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- bootstrap -->
<link href="{{ asset('assets/css/bootstrap/bootstrap.css') }}" rel="stylesheet" />
<link href="{{ asset('assets/css/bootstrap/bootstrap-overrides.css') }}" type="text/css" rel="stylesheet" />
<!-- libraries -->
<link href="{{ asset('assets/css/lib/uniform.default.css') }}" rel="stylesheet" type="text/css" />
<link href="{{ asset('assets/css/lib/select2.css') }}" type="text/css" rel="stylesheet">
<link href="{{ asset('assets/css/lib/bootstrap.datepicker.css') }}" type="text/css" rel="stylesheet">
<link href="{{ asset('assets/css/lib/font-awesome.css') }}" type="text/css" rel="stylesheet" />
<!-- global styles -->
<link rel="stylesheet" type="text/css" href="{{ asset('assets/css/compiled/layout.css') }}">
<link rel="stylesheet" type="text/css" href="{{ asset('assets/css/compiled/elements.css') }}">
<link rel="stylesheet" type="text/css" href="{{ asset('assets/css/compiled/icons.css') }}">
<!-- this page specific styles -->
<link rel="stylesheet" href="{{ asset('assets/css/compiled/index.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/compiled/user-list.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/compiled/user-profile.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/compiled/form-showcase.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="{{ asset('assets/css/lib/jquery.dataTables.css') }}" type="text/css" media="screen" />
<link rel="stylesheet" href="//cdn.datatables.net/responsive/1.0.2/css/dataTables.responsive.css" type="text/css" media="screen" />
<!-- global header javascripts -->
<script src="//code.jquery.com/jquery-latest.js"></script>
<script src="//cdn.datatables.net/1.10.3/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/responsive/1.0.2/js/dataTables.responsive.js"></script>
<script>
window.snipeit = {
settings: {
"per_page": {{{ Setting::getSettings()->per_page }}}
}
};
</script>
<!-- open sans font -->
<link href='//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
@section('styles')
h3 {
padding: 10px;
}
@show
</style>
</head>
<body>
<!-- navbar -->
<!-- navbar -->
<header class="navbar navbar-inverse" role="banner">
<div class="navbar navbar-inverse">
<div class="navbar-inner navbar-inverse">
<div class="navbar-header">
<button class="navbar-toggle" type="button" data-toggle="collapse" id="menu-toggler">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">{{{ Setting::getSettings()->site_name }}}</a>
</div>
<ul class="nav navbar-nav navbar-right">
@if (Sentry::check())
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{{ Lang::get('general.welcome', array('name' => Sentry::getUser()->first_name)) }}}
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li{{{ (Request::is('account/profile') ? ' class="active"' : '') }}}>
<a href="{{ route('view-assets') }}">
<i class="icon-check"></i> @lang('general.viewassets')
</a>
<a href="{{ route('profile') }}">
<i class="icon-user"></i> @lang('general.editprofile')
</a>
<a href="{{ route('change-password') }}">
<i class="icon-lock"></i> @lang('general.changepassword')
</a>
<a href="{{ route('change-email') }}">
<i class="icon-envelope"></i> @lang('general.changeemail')
</a>
</li>
<li class="divider"></li>
<li>
<a href="{{ route('logout') }}">
<i class="icon-off"></i>
@lang('general.logout')
</a>
</li>
</ul>
</li>
@else
<li {{{ (Request::is('auth/signin') ? 'class="active"' : '') }}}><a href="{{ route('signin') }}">@lang('general.sign_in')</a></li>
@endif
</ul>
</div>
</div>
</header>
<!-- end navbar -->
@if (Sentry::check())
<!-- sidebar -->
<div id="sidebar-nav">
<ul id="dashboard-menu">
<li><a href="{{ route('requestable-assets') }}" {{{ (Request::is('view-requestable*') ? ' class="active"' : '') }}} >@lang('admin/hardware/general.requestable')</a></li>
</ul>
</div>
<!-- end sidebar -->
@endif
<!-- main container -->
<div class="content">
<div id="pad-wrapper">
<!-- Notifications -->
@include('frontend/notifications')
<!-- Content -->
@yield('content')
</div>
</div>
</div>
</div>
<footer>
<div class="col-md-2">
</div>
<div id="footer">
<div class="col-md-9">
<div class="container">
<div class="muted credit" style="position:absolute;margin-top:1px;left:80px;margin-right:100px;">
<a target="_blank" href="http://snipeitapp.com">Snipe IT</a> is a free open source
project by <a target="_blank" href="http://twitter.com/snipeyhead">@snipeyhead</a>.</div>
<div class="muted credit" style="position:absolute;margin-top:1px;right:80px;margin-left:100px;">
<a target="_blank" href="https://github.com/snipe/snipe-it">Fork it</a> |
<a target="_blank" href="http://docs.snipeitapp.com/">Documentation</a> |
<a href="https://crowdin.com/project/snipe-it">Help Translate It! </a> |
<a target="_blank" href="https://github.com/snipe/snipe-it/issues?state=open">Report a Bug</a>
&nbsp; &nbsp; (v1.2.4)</p>
</div>
</div>
</div>
</div>
</footer>
<!-- end main container -->
<div class="modal fade" id="dataConfirmModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel"></h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button><a class="btn btn-danger" id="dataConfirmOK">@lang('general.yes')</a>
</div>
</div>
</div>
</div>
<!-- scripts -->
<script src="{{ asset('assets/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('assets/js/jquery.knob.js') }}"></script>
<script src="{{ asset('assets/js/select2.min.js') }}"></script>
<script src="{{ asset('assets/js/jquery.uniform.min.js') }}"></script>
<script src="{{ asset('assets/js/bootstrap.datepicker.js') }}"></script>
<script src="{{ asset('assets/js/theme.js') }}"></script>
<script src="{{ asset('assets/js/snipeit.js') }}"></script>
</body>
</html>
+2 -1
View File
@@ -26,7 +26,8 @@
"intervention/image": "dev-master"
},
"require-dev": {
"phpunit/phpunit": "*"
"phpunit/phpunit": "*",
"mockery/mockery": "0.9.*"
},
"autoload": {
"classmap": [
Generated
+119 -53
View File
@@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "b2d1b48bc514e40f1a4ef04cd86aa86f",
"hash": "4242b20dc02d70aa7d97a211ea1e58b8",
"packages": [
{
"name": "bacon/bacon-qr-code",
@@ -1194,12 +1194,12 @@
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "7583a2b96b9fda7ece90e34a23cd46e4858b3352"
"reference": "f05ed3a44a8e40533d4cf60a0669db6b1887b499"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/7583a2b96b9fda7ece90e34a23cd46e4858b3352",
"reference": "7583a2b96b9fda7ece90e34a23cd46e4858b3352",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/f05ed3a44a8e40533d4cf60a0669db6b1887b499",
"reference": "f05ed3a44a8e40533d4cf60a0669db6b1887b499",
"shasum": ""
},
"require": {
@@ -1258,7 +1258,7 @@
"logging",
"psr-3"
],
"time": "2015-01-29 16:05:08"
"time": "2015-02-11 14:20:33"
},
{
"name": "nesbot/carbon",
@@ -1756,12 +1756,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Config.git",
"reference": "1624dd47e1f4dc89ae4e7ca4a0476325042f8e82"
"reference": "a634f4e901f5d20696020980cae70d8d94c6193d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Config/zipball/1624dd47e1f4dc89ae4e7ca4a0476325042f8e82",
"reference": "1624dd47e1f4dc89ae4e7ca4a0476325042f8e82",
"url": "https://api.github.com/repos/symfony/Config/zipball/a634f4e901f5d20696020980cae70d8d94c6193d",
"reference": "a634f4e901f5d20696020980cae70d8d94c6193d",
"shasum": ""
},
"require": {
@@ -1795,7 +1795,7 @@
],
"description": "Symfony Config Component",
"homepage": "http://symfony.com",
"time": "2015-01-25 04:39:35"
"time": "2015-02-11 07:17:51"
},
{
"name": "symfony/console",
@@ -1804,12 +1804,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Console.git",
"reference": "767a4be52d062d49bb0ef5f593f5f5d06b2f5ff3"
"reference": "a43e750b4c74f3bdfca77c79c343033d35a6cd6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Console/zipball/767a4be52d062d49bb0ef5f593f5f5d06b2f5ff3",
"reference": "767a4be52d062d49bb0ef5f593f5f5d06b2f5ff3",
"url": "https://api.github.com/repos/symfony/Console/zipball/a43e750b4c74f3bdfca77c79c343033d35a6cd6e",
"reference": "a43e750b4c74f3bdfca77c79c343033d35a6cd6e",
"shasum": ""
},
"require": {
@@ -1850,7 +1850,7 @@
],
"description": "Symfony Console Component",
"homepage": "http://symfony.com",
"time": "2015-02-05 06:31:40"
"time": "2015-02-08 07:07:45"
},
{
"name": "symfony/css-selector",
@@ -2022,12 +2022,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/EventDispatcher.git",
"reference": "e9298668dce8dd219d1ee2290c7f313954f1f984"
"reference": "2dc33aff298b20ad099ac456034aebc5055f02fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/e9298668dce8dd219d1ee2290c7f313954f1f984",
"reference": "e9298668dce8dd219d1ee2290c7f313954f1f984",
"url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/2dc33aff298b20ad099ac456034aebc5055f02fb",
"reference": "2dc33aff298b20ad099ac456034aebc5055f02fb",
"shasum": ""
},
"require": {
@@ -2071,7 +2071,7 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "http://symfony.com",
"time": "2015-02-05 06:58:17"
"time": "2015-02-11 07:17:51"
},
{
"name": "symfony/filesystem",
@@ -2080,12 +2080,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Filesystem.git",
"reference": "e681ca515e1e668a551b089177867e62e03d7d2d"
"reference": "177e0a8e29fab3f0556f7a973b5a42935e42a4d7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/e681ca515e1e668a551b089177867e62e03d7d2d",
"reference": "e681ca515e1e668a551b089177867e62e03d7d2d",
"url": "https://api.github.com/repos/symfony/Filesystem/zipball/177e0a8e29fab3f0556f7a973b5a42935e42a4d7",
"reference": "177e0a8e29fab3f0556f7a973b5a42935e42a4d7",
"shasum": ""
},
"require": {
@@ -2118,7 +2118,7 @@
],
"description": "Symfony Filesystem Component",
"homepage": "http://symfony.com",
"time": "2015-01-09 06:51:41"
"time": "2015-02-11 07:17:51"
},
{
"name": "symfony/finder",
@@ -2174,12 +2174,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpFoundation.git",
"reference": "749f478499b89aaf53bdd6c80743fc0c3a72cce4"
"reference": "79b2385ee420944ab89c6972acae9c7c8cb9a412"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/749f478499b89aaf53bdd6c80743fc0c3a72cce4",
"reference": "749f478499b89aaf53bdd6c80743fc0c3a72cce4",
"url": "https://api.github.com/repos/symfony/HttpFoundation/zipball/79b2385ee420944ab89c6972acae9c7c8cb9a412",
"reference": "79b2385ee420944ab89c6972acae9c7c8cb9a412",
"shasum": ""
},
"require": {
@@ -2218,7 +2218,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "http://symfony.com",
"time": "2015-02-05 06:31:40"
"time": "2015-02-08 07:07:45"
},
{
"name": "symfony/http-kernel",
@@ -2227,12 +2227,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/HttpKernel.git",
"reference": "122057675f27f41b25b5811523516cc018eb28ed"
"reference": "b481edb3c476dcd2040443f38292c1fadd2fac88"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/122057675f27f41b25b5811523516cc018eb28ed",
"reference": "122057675f27f41b25b5811523516cc018eb28ed",
"url": "https://api.github.com/repos/symfony/HttpKernel/zipball/b481edb3c476dcd2040443f38292c1fadd2fac88",
"reference": "b481edb3c476dcd2040443f38292c1fadd2fac88",
"shasum": ""
},
"require": {
@@ -2292,7 +2292,7 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "http://symfony.com",
"time": "2015-02-02 14:03:24"
"time": "2015-02-08 07:08:16"
},
{
"name": "symfony/process",
@@ -2301,12 +2301,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Process.git",
"reference": "daaa39a0d7462c225f711b20dc8f5896bdab92ff"
"reference": "00a1308e8b5aec5eba7c8f1708426a78f929be8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Process/zipball/daaa39a0d7462c225f711b20dc8f5896bdab92ff",
"reference": "daaa39a0d7462c225f711b20dc8f5896bdab92ff",
"url": "https://api.github.com/repos/symfony/Process/zipball/00a1308e8b5aec5eba7c8f1708426a78f929be8c",
"reference": "00a1308e8b5aec5eba7c8f1708426a78f929be8c",
"shasum": ""
},
"require": {
@@ -2339,7 +2339,7 @@
],
"description": "Symfony Process Component",
"homepage": "http://symfony.com",
"time": "2015-02-05 08:31:48"
"time": "2015-02-08 07:07:45"
},
{
"name": "symfony/routing",
@@ -2348,12 +2348,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Routing.git",
"reference": "8743280059d6d74db4a7fb58bbe049bd795195a9"
"reference": "46142c34ea830f47429df6e15faec3a33292d618"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Routing/zipball/8743280059d6d74db4a7fb58bbe049bd795195a9",
"reference": "8743280059d6d74db4a7fb58bbe049bd795195a9",
"url": "https://api.github.com/repos/symfony/Routing/zipball/46142c34ea830f47429df6e15faec3a33292d618",
"reference": "46142c34ea830f47429df6e15faec3a33292d618",
"shasum": ""
},
"require": {
@@ -2407,7 +2407,7 @@
"uri",
"url"
],
"time": "2015-02-05 06:31:40"
"time": "2015-02-08 07:07:45"
},
{
"name": "symfony/security-core",
@@ -2479,12 +2479,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Stopwatch.git",
"reference": "f6ce5e09596ec0493ef42acf5eb0b38218733e48"
"reference": "2883cdac7f23a0355760e485d6906528ad1e9504"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/f6ce5e09596ec0493ef42acf5eb0b38218733e48",
"reference": "f6ce5e09596ec0493ef42acf5eb0b38218733e48",
"url": "https://api.github.com/repos/symfony/Stopwatch/zipball/2883cdac7f23a0355760e485d6906528ad1e9504",
"reference": "2883cdac7f23a0355760e485d6906528ad1e9504",
"shasum": ""
},
"require": {
@@ -2517,7 +2517,7 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "http://symfony.com",
"time": "2015-01-09 06:51:41"
"time": "2015-02-11 07:17:51"
},
{
"name": "symfony/translation",
@@ -2639,12 +2639,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/Yaml.git",
"reference": "02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60"
"reference": "43aac3461a5679f486f7c96e4d7e780a59fec997"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60",
"reference": "02ba3dc638c5d3f0ab3b47ddb74f98c11dcc0c60",
"url": "https://api.github.com/repos/symfony/Yaml/zipball/43aac3461a5679f486f7c96e4d7e780a59fec997",
"reference": "43aac3461a5679f486f7c96e4d7e780a59fec997",
"shasum": ""
},
"require": {
@@ -2677,7 +2677,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "http://symfony.com",
"time": "2015-01-25 04:39:35"
"time": "2015-02-11 07:17:51"
}
],
"packages-dev": [
@@ -2735,6 +2735,72 @@
],
"time": "2015-01-16 19:29:51"
},
{
"name": "mockery/mockery",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/padraic/mockery.git",
"reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/padraic/mockery/zipball/f770ab0cf167cccf1a701f28411fbfc9971ff90e",
"reference": "f770ab0cf167cccf1a701f28411fbfc9971ff90e",
"shasum": ""
},
"require": {
"lib-pcre": ">=7.0",
"php": ">=5.3.2"
},
"require-dev": {
"hamcrest/hamcrest-php": "~1.1",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.7@dev"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.9.x-dev"
}
},
"autoload": {
"psr-0": {
"Mockery": "library/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
},
{
"name": "Dave Marshall",
"email": "dave.marshall@atstsolutions.co.uk",
"homepage": "http://davedevelopment.co.uk"
}
],
"description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.",
"homepage": "http://github.com/padraic/mockery",
"keywords": [
"BDD",
"TDD",
"library",
"mock",
"mock objects",
"mockery",
"stub",
"test",
"test double",
"testing"
],
"time": "2015-02-11 12:43:02"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "dev-master",
@@ -2790,12 +2856,12 @@
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "d647e27524f9f7edc37baf63a114b52f5975808f"
"reference": "3a9204c44667c302049ab4eadb02daab789e19ed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/d647e27524f9f7edc37baf63a114b52f5975808f",
"reference": "d647e27524f9f7edc37baf63a114b52f5975808f",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/3a9204c44667c302049ab4eadb02daab789e19ed",
"reference": "3a9204c44667c302049ab4eadb02daab789e19ed",
"shasum": ""
},
"require": {
@@ -2842,7 +2908,7 @@
"spy",
"stub"
],
"time": "2015-01-26 10:50:16"
"time": "2015-02-09 17:43:38"
},
{
"name": "phpunit/php-code-coverage",
@@ -3094,12 +3160,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "2b1e1e267d0286538b1762aa2c79a96ae1e583c8"
"reference": "7c1de6a854a36ba330b352a005a4f5f928619f53"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2b1e1e267d0286538b1762aa2c79a96ae1e583c8",
"reference": "2b1e1e267d0286538b1762aa2c79a96ae1e583c8",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/7c1de6a854a36ba330b352a005a4f5f928619f53",
"reference": "7c1de6a854a36ba330b352a005a4f5f928619f53",
"shasum": ""
},
"require": {
@@ -3158,7 +3224,7 @@
"testing",
"xunit"
],
"time": "2015-02-06 05:41:08"
"time": "2015-02-09 06:38:12"
},
{
"name": "phpunit/phpunit-mock-objects",
+94
View File
@@ -0,0 +1,94 @@
table.dataTable.dtr-inline.collapsed tbody td:first-child,
table.dataTable.dtr-inline.collapsed tbody th:first-child {
position: relative;
padding-left: 30px;
cursor: pointer;
}
table.dataTable.dtr-inline.collapsed tbody td:first-child:before,
table.dataTable.dtr-inline.collapsed tbody th:first-child:before {
top: 8px;
left: 4px;
height: 16px;
width: 16px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
text-align: center;
line-height: 14px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-inline.collapsed tbody td:first-child.dataTables_empty:before,
table.dataTable.dtr-inline.collapsed tbody th:first-child.dataTables_empty:before {
display: none;
}
table.dataTable.dtr-inline.collapsed tbody tr.parent td:first-child:before,
table.dataTable.dtr-inline.collapsed tbody tr.parent th:first-child:before {
content: '-';
background-color: #d33333;
}
table.dataTable.dtr-inline.collapsed tbody tr.child td:before {
display: none;
}
table.dataTable.dtr-column tbody td.control,
table.dataTable.dtr-column tbody th.control {
position: relative;
cursor: pointer;
}
table.dataTable.dtr-column tbody td.control:before,
table.dataTable.dtr-column tbody th.control:before {
top: 50%;
left: 50%;
height: 16px;
width: 16px;
margin-top: -10px;
margin-left: -10px;
display: block;
position: absolute;
color: white;
border: 2px solid white;
border-radius: 16px;
text-align: center;
line-height: 14px;
box-shadow: 0 0 3px #444;
box-sizing: content-box;
content: '+';
background-color: #31b131;
}
table.dataTable.dtr-column tbody tr.parent td.control:before,
table.dataTable.dtr-column tbody tr.parent th.control:before {
content: '-';
background-color: #d33333;
}
table.dataTable tr.child {
padding: 0.5em 1em;
}
table.dataTable tr.child:hover {
background: transparent !important;
}
table.dataTable tr.child ul {
display: inline-block;
list-style-type: none;
margin: 0;
padding: 0;
}
table.dataTable tr.child ul li {
border-bottom: 1px solid #efefef;
padding: 0.5em 0;
}
table.dataTable tr.child ul li:first-child {
padding-top: 0;
}
table.dataTable tr.child ul li:last-child {
border-bottom: none;
}
table.dataTable tr.child span.dtr-title {
display: inline-block;
min-width: 75px;
font-weight: bold;
}
+61
View File
@@ -0,0 +1,61 @@
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
src: local('Open Sans Light'), local('OpenSans-Light'), url(http://fonts.gstatic.com/s/opensans/v10/DXI1ORHCpsQm3Vp6mXoaTZS3E-kSBmtLoNJPDtbj2Pk.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
src: local('Open Sans'), local('OpenSans'), url(http://fonts.gstatic.com/s/opensans/v10/cJZKeOuBrn4kERxqtaUH3SZ2oysoEQEeKwjgmXLRnTc.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 600;
src: local('Open Sans Semibold'), local('OpenSans-Semibold'), url(http://fonts.gstatic.com/s/opensans/v10/MTP_ySUJH_bn48VBG8sNSpS3E-kSBmtLoNJPDtbj2Pk.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
src: local('Open Sans Bold'), local('OpenSans-Bold'), url(http://fonts.gstatic.com/s/opensans/v10/k3k702ZOKiLJc3WVjuplzJS3E-kSBmtLoNJPDtbj2Pk.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: 800;
src: local('Open Sans Extrabold'), local('OpenSans-Extrabold'), url(http://fonts.gstatic.com/s/opensans/v10/EInbV5DfGHOiMmvb1Xr-hpS3E-kSBmtLoNJPDtbj2Pk.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 300;
src: local('Open Sans Light Italic'), local('OpenSansLight-Italic'), url(http://fonts.gstatic.com/s/opensans/v10/PRmiXeptR36kaC0GEAetxt6Naowg1QhaIq8kLGtQSos.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 400;
src: local('Open Sans Italic'), local('OpenSans-Italic'), url(http://fonts.gstatic.com/s/opensans/v10/xjAJXh38I15wypJXxuGMBiwlidHJgAgmTjOEEzwu1L8.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 600;
src: local('Open Sans Semibold Italic'), local('OpenSans-SemiboldItalic'), url(http://fonts.gstatic.com/s/opensans/v10/PRmiXeptR36kaC0GEAetxs1QGe9x6ME_FQCWJB3n6z8.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 700;
src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), url(http://fonts.gstatic.com/s/opensans/v10/PRmiXeptR36kaC0GEAetxjdGNerWpg2Hn6A-BxWgZ_I.ttf) format('truetype');
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: 800;
src: local('Open Sans Extrabold Italic'), local('OpenSans-ExtraboldItalic'), url(http://fonts.gstatic.com/s/opensans/v10/PRmiXeptR36kaC0GEAetxkdJXfhP-2RmnAuS9A2rxpE.ttf) format('truetype');
}
+802
View File
@@ -0,0 +1,802 @@
/*! Responsive 1.0.2
* 2014 SpryMedia Ltd - datatables.net/license
*/
/**
* @summary Responsive
* @description Responsive tables plug-in for DataTables
* @version 1.0.2
* @file dataTables.responsive.js
* @author SpryMedia Ltd (www.sprymedia.co.uk)
* @contact www.sprymedia.co.uk/contact
* @copyright Copyright 2014 SpryMedia Ltd.
*
* This source file is free software, available under the following license:
* MIT license - http://datatables.net/license/mit
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
*
* For details please refer to: http://www.datatables.net
*/
(function(window, document, undefined) {
var factory = function( $, DataTable ) {
"use strict";
/**
* Responsive is a plug-in for the DataTables library that makes use of
* DataTables' ability to change the visibility of columns, changing the
* visibility of columns so the displayed columns fit into the table container.
* The end result is that complex tables will be dynamically adjusted to fit
* into the viewport, be it on a desktop, tablet or mobile browser.
*
* Responsive for DataTables has two modes of operation, which can used
* individually or combined:
*
* * Class name based control - columns assigned class names that match the
* breakpoint logic can be shown / hidden as required for each breakpoint.
* * Automatic control - columns are automatically hidden when there is no
* room left to display them. Columns removed from the right.
*
* In additional to column visibility control, Responsive also has built into
* options to use DataTables' child row display to show / hide the information
* from the table that has been hidden. There are also two modes of operation
* for this child row display:
*
* * Inline - when the control element that the user can use to show / hide
* child rows is displayed inside the first column of the table.
* * Column - where a whole column is dedicated to be the show / hide control.
*
* Initialisation of Responsive is performed by:
*
* * Adding the class `responsive` or `dt-responsive` to the table. In this case
* Responsive will automatically be initialised with the default configuration
* options when the DataTable is created.
* * Using the `responsive` option in the DataTables configuration options. This
* can also be used to specify the configuration options, or simply set to
* `true` to use the defaults.
*
* @class
* @param {object} settings DataTables settings object for the host table
* @param {object} [opts] Configuration options
* @requires jQuery 1.7+
* @requires DataTables 1.10.1+
*
* @example
* $('#example').DataTable( {
* responsive: true
* } );
* } );
*/
var Responsive = function ( settings, opts ) {
// Sanity check that we are using DataTables 1.10 or newer
if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.1' ) ) {
throw 'DataTables Responsive requires DataTables 1.10.1 or newer';
}
this.s = {
dt: new DataTable.Api( settings ),
columns: []
};
// Check if responsive has already been initialised on this table
if ( this.s.dt.settings()[0].responsive ) {
return;
}
// details is an object, but for simplicity the user can give it as a string
if ( opts && typeof opts.details === 'string' ) {
opts.details = { type: opts.details };
}
this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
settings.responsive = this;
this._constructor();
};
Responsive.prototype = {
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Constructor
*/
/**
* Initialise the Responsive instance
*
* @private
*/
_constructor: function ()
{
var that = this;
var dt = this.s.dt;
dt.settings()[0]._responsive = this;
// Use DataTables' private throttle function to avoid processor thrashing
$(window).on( 'resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle( function () {
that._resize();
} ) );
// Destroy event handler
dt.on( 'destroy.dtr', function () {
$(window).off( 'resize.dtr orientationchange.dtr' );
} );
// Reorder the breakpoints array here in case they have been added out
// of order
this.c.breakpoints.sort( function (a, b) {
return a.width < b.width ? 1 :
a.width > b.width ? -1 : 0;
} );
// Determine which columns are already hidden, and should therefore
// remain hidden. TODO - should this be done? See thread 22677
//
// this.s.alwaysHidden = dt.columns(':hidden').indexes();
this._classLogic();
this._resizeAuto();
// First pass - draw the table for the current viewport size
this._resize();
// Details handler
var details = this.c.details;
if ( details.type ) {
that._detailsInit();
this._detailsVis();
dt.on( 'column-visibility.dtr', function () {
that._detailsVis();
} );
$(dt.table().node()).addClass( 'dtr-'+details.type );
}
},
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Private methods
*/
/**
* Calculate the visibility for the columns in a table for a given
* breakpoint. The result is pre-determined based on the class logic if
* class names are used to control all columns, but the width of the table
* is also used if there are columns which are to be automatically shown
* and hidden.
*
* @param {string} breakpoint Breakpoint name to use for the calculation
* @return {array} Array of boolean values initiating the visibility of each
* column.
* @private
*/
_columnsVisiblity: function ( breakpoint )
{
var dt = this.s.dt;
var columns = this.s.columns;
var i, ien;
// Class logic - determine which columns are in this breakpoint based
// on the classes. If no class control (i.e. `auto`) then `-` is used
// to indicate this to the rest of the function
var display = $.map( columns, function ( col ) {
return col.auto && col.minWidth === null ?
false :
col.auto === true ?
'-' :
$.inArray( breakpoint, col.includeIn ) !== -1;
} );
// Auto column control - first pass: how much width is taken by the
// ones that must be included from the non-auto columns
var requiredWidth = 0;
for ( i=0, ien=display.length ; i<ien ; i++ ) {
if ( display[i] === true ) {
requiredWidth += columns[i].minWidth;
}
}
// Second pass, use up any remaining width for other columns
var widthAvailable = dt.table().container().offsetWidth;
var usedWidth = widthAvailable - requiredWidth;
for ( i=0, ien=display.length ; i<ien ; i++ ) {
// Control column needs to always be included. This makes it sub-
// optimal in terms of using the available with, but to stop layout
// thrashing or overflow
if ( columns[i].control ) {
usedWidth -= columns[i].minWidth;
}
else if ( display[i] === '-' ) {
// Otherwise, remove the width
display[i] = usedWidth - columns[i].minWidth < 0 ?
false :
true;
// Continue counting down the width, so a smaller column to the
// left won't be shown
usedWidth -= columns[i].minWidth;
}
}
// Determine if the 'control' column should be shown (if there is one).
// This is the case when there is a hidden column (that is not the
// control column). The two loops look inefficient here, but they are
// trivial and will fly through. We need to know the outcome from the
// first , before the action in the second can be taken
var showControl = false;
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
showControl = true;
break;
}
}
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
if ( columns[i].control ) {
display[i] = showControl;
}
}
// Finally we need to make sure that there is at least one column that
// is visible
if ( $.inArray( true, display ) === -1 ) {
display[0] = true;
}
return display;
},
/**
* Create the internal `columns` array with information about the columns
* for the table. This includes determining which breakpoints the column
* will appear in, based upon class names in the column, which makes up the
* vast majority of this method.
*
* @private
*/
_classLogic: function ()
{
var that = this;
var calc = {};
var breakpoints = this.c.breakpoints;
var columns = this.s.dt.columns().eq(0).map( function (i) {
var className = this.column(i).header().className;
return {
className: className,
includeIn: [],
auto: false,
control: false,
never: className.match(/\bnever\b/) ? true : false
};
} );
// Simply add a breakpoint to `includeIn` array, ensuring that there are
// no duplicates
var add = function ( colIdx, name ) {
var includeIn = columns[ colIdx ].includeIn;
if ( $.inArray( name, includeIn ) === -1 ) {
includeIn.push( name );
}
};
var column = function ( colIdx, name, operator, matched ) {
var size, i, ien;
if ( ! operator ) {
columns[ colIdx ].includeIn.push( name );
}
else if ( operator === 'max-' ) {
// Add this breakpoint and all smaller
size = that._find( name ).width;
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].width <= size ) {
add( colIdx, breakpoints[i].name );
}
}
}
else if ( operator === 'min-' ) {
// Add this breakpoint and all larger
size = that._find( name ).width;
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].width >= size ) {
add( colIdx, breakpoints[i].name );
}
}
}
else if ( operator === 'not-' ) {
// Add all but this breakpoint (xxx need extra information)
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
add( colIdx, breakpoints[i].name );
}
}
}
};
// Loop over each column and determine if it has a responsive control
// class
columns.each( function ( col, i ) {
var classNames = col.className.split(' ');
var hasClass = false;
// Split the class name up so multiple rules can be applied if needed
for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
var className = $.trim( classNames[k] );
if ( className === 'all' ) {
// Include in all
hasClass = true;
col.includeIn = $.map( breakpoints, function (a) {
return a.name;
} );
return;
}
else if ( className === 'none' || className === 'never' ) {
// Include in none (default) and no auto
hasClass = true;
return;
}
else if ( className === 'control' ) {
// Special column that is only visible, when one of the other
// columns is hidden. This is used for the details control
hasClass = true;
col.control = true;
return;
}
$.each( breakpoints, function ( j, breakpoint ) {
// Does this column have a class that matches this breakpoint?
var brokenPoint = breakpoint.name.split('-');
var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
var match = className.match( re );
if ( match ) {
hasClass = true;
if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
// Class name matches breakpoint name fully
column( i, breakpoint.name, match[1], match[2]+match[3] );
}
else if ( match[2] === brokenPoint[0] && ! match[3] ) {
// Class name matched primary breakpoint name with no qualifier
column( i, breakpoint.name, match[1], match[2] );
}
}
} );
}
// If there was no control class, then automatic sizing is used
if ( ! hasClass ) {
col.auto = true;
}
} );
this.s.columns = columns;
},
/**
* Initialisation for the details handler
*
* @private
*/
_detailsInit: function ()
{
var that = this;
var dt = this.s.dt;
var details = this.c.details;
// The inline type always uses the first child as the target
if ( details.type === 'inline' ) {
details.target = 'td:first-child';
}
// type.target can be a string jQuery selector or a column index
var target = details.target;
var selector = typeof target === 'string' ? target : 'td';
// Click handler to show / hide the details rows when they are available
$( dt.table().body() ).on( 'click', selector, function (e) {
// If the table is not collapsed (i.e. there is no hidden columns)
// then take no action
if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
return;
}
// Check that the row is actually a DataTable's controlled node
if ( ! dt.row( $(this).closest('tr') ).length ) {
return;
}
// For column index, we determine if we should act or not in the
// handler - otherwise it is already okay
if ( typeof target === 'number' ) {
var targetIdx = target < 0 ?
dt.columns().eq(0).length + target :
target;
if ( dt.cell( this ).index().column !== targetIdx ) {
return;
}
}
// $().closest() includes itself in its check
var row = dt.row( $(this).closest('tr') );
if ( row.child.isShown() ) {
row.child( false );
$( row.node() ).removeClass( 'parent' );
}
else {
var info = that.c.details.renderer( dt, row[0] );
row.child( info, 'child' ).show();
$( row.node() ).addClass( 'parent' );
}
} );
},
/**
* Update the child rows in the table whenever the column visibility changes
*
* @private
*/
_detailsVis: function ()
{
var that = this;
var dt = this.s.dt;
// Find how many columns are hidden
var hiddenColumns = dt.columns().indexes().filter( function ( idx ) {
var col = dt.column( idx );
if ( col.visible() ) {
return null;
}
// Only counts as hidden if it doesn't have the `never` class
return $( col.header() ).hasClass( 'never' ) ? null : idx;
} );
var haveHidden = true;
if ( hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[ hiddenColumns[0] ].control ) ) {
haveHidden = false;
}
if ( haveHidden ) {
// Got hidden columns
$( dt.table().node() ).addClass('collapsed');
// Show all existing child rows
dt.rows().eq(0).each( function (idx) {
var row = dt.row( idx );
if ( row.child() ) {
var info = that.c.details.renderer( dt, row[0] );
// The renderer can return false to have no child row
if ( info === false ) {
row.child.hide();
}
else {
row.child( info, 'child' ).show();
}
}
} );
}
else {
// No hidden columns
$( dt.table().node() ).removeClass('collapsed');
// Hide all existing child rows
dt.rows().eq(0).each( function (idx) {
dt.row( idx ).child.hide();
} );
}
},
/**
* Find a breakpoint object from a name
* @param {string} name Breakpoint name to find
* @return {object} Breakpoint description object
*/
_find: function ( name )
{
var breakpoints = this.c.breakpoints;
for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
if ( breakpoints[i].name === name ) {
return breakpoints[i];
}
}
},
/**
* Alter the table display for a resized viewport. This involves first
* determining what breakpoint the window currently is in, getting the
* column visibilities to apply and then setting them.
*
* @private
*/
_resize: function ()
{
var dt = this.s.dt;
var width = $(window).width();
var breakpoints = this.c.breakpoints;
var breakpoint = breakpoints[0].name;
// Determine what breakpoint we are currently at
for ( var i=breakpoints.length-1 ; i>=0 ; i-- ) {
if ( width <= breakpoints[i].width ) {
breakpoint = breakpoints[i].name;
break;
}
}
// Show the columns for that break point
var columns = this._columnsVisiblity( breakpoint );
dt.columns().eq(0).each( function ( colIdx, i ) {
dt.column( colIdx ).visible( columns[i] );
} );
},
/**
* Determine the width of each column in the table so the auto column hiding
* has that information to work with. This method is never going to be 100%
* perfect since column widths can change slightly per page, but without
* seriously compromising performance this is quite effective.
*
* @private
*/
_resizeAuto: function ()
{
var dt = this.s.dt;
var columns = this.s.columns;
// Are we allowed to do auto sizing?
if ( ! this.c.auto ) {
return;
}
// Are there any columns that actually need auto-sizing, or do they all
// have classes defined
if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
return;
}
// Clone the table with the current data in it
var tableWidth = dt.table().node().offsetWidth;
var columnWidths = dt.columns;
var clonedTable = dt.table().node().cloneNode( false );
var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
var clonedBody = $( dt.table().body().cloneNode( false ) ).appendTo( clonedTable );
// This is a bit slow, but we need to get a clone of each row that
// includes all columns. As such, try to do this as little as possible.
dt.rows( { page: 'current' } ).indexes().flatten().each( function ( idx ) {
var clone = dt.row( idx ).node().cloneNode( true );
if ( dt.columns( ':hidden' ).flatten().length ) {
$(clone).append( dt.cells( idx, ':hidden' ).nodes().to$().clone() );
}
$(clone).appendTo( clonedBody );
} );
var cells = dt.columns().header().to$().clone( false ).wrapAll('tr').appendTo( clonedHeader );
var inserted = $('<div/>')
.css( {
width: 1,
height: 1,
overflow: 'hidden'
} )
.append( clonedTable )
.insertBefore( dt.table().node() );
// The cloned header now contains the smallest that each column can be
dt.columns().eq(0).each( function ( idx ) {
columns[idx].minWidth = cells[ idx ].offsetWidth || 0;
} );
inserted.remove();
}
};
/**
* List of default breakpoints. Each item in the array is an object with two
* properties:
*
* * `name` - the breakpoint name.
* * `width` - the breakpoint width
*
* @name Responsive.breakpoints
* @static
*/
Responsive.breakpoints = [
{ name: 'desktop', width: Infinity },
{ name: 'tablet-l', width: 1024 },
{ name: 'tablet-p', width: 768 },
{ name: 'mobile-l', width: 480 },
{ name: 'mobile-p', width: 320 }
];
/**
* Responsive default settings for initialisation
*
* @namespace
* @name Responsive.defaults
* @static
*/
Responsive.defaults = {
/**
* List of breakpoints for the instance. Note that this means that each
* instance can have its own breakpoints. Additionally, the breakpoints
* cannot be changed once an instance has been creased.
*
* @type {Array}
* @default Takes the value of `Responsive.breakpoints`
*/
breakpoints: Responsive.breakpoints,
/**
* Enable / disable auto hiding calculations. It can help to increase
* performance slightly if you disable this option, but all columns would
* need to have breakpoint classes assigned to them
*
* @type {Boolean}
* @default `true`
*/
auto: true,
/**
* Details control. If given as a string value, the `type` property of the
* default object is set to that value, and the defaults used for the rest
* of the object - this is for ease of implementation.
*
* The object consists of the following properties:
*
* * `renderer` - function that is called for display of the child row data.
* The default function will show the data from the hidden columns
* * `target` - Used as the selector for what objects to attach the child
* open / close to
* * `type` - `false` to disable the details display, `inline` or `column`
* for the two control types
*
* @type {Object|string}
*/
details: {
renderer: function ( api, rowIdx ) {
var data = api.cells( rowIdx, ':hidden' ).eq(0).map( function ( cell ) {
var header = $( api.column( cell.column ).header() );
var idx = api.cell( cell ).index();
if ( header.hasClass( 'control' ) || header.hasClass( 'never' ) ) {
return '';
}
// Use a non-public DT API method to render the data for display
// This needs to be updated when DT adds a suitable method for
// this type of data retrieval
var dtPrivate = api.settings()[0];
var cellData = dtPrivate.oApi._fnGetCellData(
dtPrivate, idx.row, idx.column, 'display'
);
return '<li data-dtr-index="'+idx.column+'">'+
'<span class="dtr-title">'+
header.text()+':'+
'</span> '+
'<span class="dtr-data">'+
cellData+
'</span>'+
'</li>';
} ).toArray().join('');
return data ?
$('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
false;
},
target: 0,
type: 'inline'
}
};
/*
* API
*/
var Api = $.fn.dataTable.Api;
// Doesn't do anything - work around for a bug in DT... Not documented
Api.register( 'responsive()', function () {
return this;
} );
Api.register( 'responsive.recalc()', function () {
this.iterator( 'table', function ( ctx ) {
if ( ctx._responsive ) {
ctx._responsive._resizeAuto();
ctx._responsive._resize();
}
} );
} );
Api.register( 'responsive.index()', function ( li ) {
li = $(li);
return {
column: li.data('dtr-index'),
row: li.parent().data('dtr-index')
};
} );
/**
* Version information
*
* @name Responsive.version
* @static
*/
Responsive.version = '1.0.2';
$.fn.dataTable.Responsive = Responsive;
$.fn.DataTable.Responsive = Responsive;
// Attach a listener to the document which listens for DataTables initialisation
// events so we can automatically initialise
$(document).on( 'init.dt.dtr', function (e, settings, json) {
if ( $(settings.nTable).hasClass( 'responsive' ) ||
$(settings.nTable).hasClass( 'dt-responsive' ) ||
settings.oInit.responsive ||
DataTable.defaults.responsive
) {
var init = settings.oInit.responsive;
if ( init !== false ) {
new Responsive( settings, $.isPlainObject( init ) ? init : {} );
}
}
} );
return Responsive;
}; // /factory
// Define as an AMD module if possible
if ( typeof define === 'function' && define.amd ) {
define( ['jquery', 'datatables'], factory );
}
else if ( typeof exports === 'object' ) {
// Node/CommonJS
factory( require('jquery'), require('datatables') );
}
else if ( jQuery && !jQuery.fn.dataTable.Responsive ) {
// Otherwise simply initialise as normal, stopping multiple evaluation
factory( jQuery, jQuery.fn.dataTable );
}
})(window, document);
+8
View File
@@ -0,0 +1,8 @@
/*
HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>";
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:"3.7.0",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);
if(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
+10309
View File
File diff suppressed because it is too large Load Diff
+3493
View File
File diff suppressed because it is too large Load Diff