diff --git a/app/Http/Controllers/DeploymentController.php b/app/Http/Controllers/DeploymentController.php index 69d3daddf..5b3bc0790 100644 --- a/app/Http/Controllers/DeploymentController.php +++ b/app/Http/Controllers/DeploymentController.php @@ -72,6 +72,7 @@ public function project($project_id) 'sharedFiles' => $project->sharedFiles, 'projectFiles' => $project->projectFiles, 'checkUrls' => $project->checkUrls, + 'variables' => $project->variables, 'optional' => $optional, 'route' => 'commands', ]); diff --git a/app/Http/Controllers/Resources/VariableController.php b/app/Http/Controllers/Resources/VariableController.php new file mode 100644 index 000000000..c1dfaf182 --- /dev/null +++ b/app/Http/Controllers/Resources/VariableController.php @@ -0,0 +1,56 @@ +repository = $repository; + } + + /** + * Store a newly created variable in storage. + * + * @param StoreVariableRequest $request + * @return Response + */ + public function store(StoreVariableRequest $request) + { + return $this->repository->create($request->only( + 'name', + 'value', + 'project_id' + )); + } + + /** + * Update the specified variable in storage. + * + * @param int $variable_id + * @param StoreVariableRequest $request + * @return Response + */ + public function update($variable_id, StoreVariableRequest $request) + { + return $this->repository->updateById($request->only( + 'name', + 'value', + 'project_id' + ), $variable_id); + } +} diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 7c2d53fb4..45603520a 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -7,6 +7,7 @@ /** * Generic Request class. + * @SuppressWarnings(PHPMD.NumberOfChildren) */ abstract class Request extends FormRequest { diff --git a/app/Http/Requests/StoreVariableRequest.php b/app/Http/Requests/StoreVariableRequest.php new file mode 100644 index 000000000..701b59218 --- /dev/null +++ b/app/Http/Requests/StoreVariableRequest.php @@ -0,0 +1,25 @@ + 'required|max:255', + 'value' => 'required', + 'project_id' => 'required|integer|exists:projects,id', + ]; + } +} diff --git a/app/Http/routes.php b/app/Http/routes.php index fe24e0727..4212d3879 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -57,6 +57,7 @@ ]; Route::resource('servers', 'ServerController', $actions); + Route::resource('variables', 'VariableController', $actions); Route::resource('commands', 'CommandController', $actions); Route::resource('heartbeats', 'HeartbeatController', $actions); Route::resource('notifications', 'NotificationController', $actions); diff --git a/app/Jobs/DeployProject.php b/app/Jobs/DeployProject.php index f479ed4c8..ac79d6e69 100644 --- a/app/Jobs/DeployProject.php +++ b/app/Jobs/DeployProject.php @@ -459,7 +459,15 @@ private function getScript(DeployStep $step, Server $server) $commands = implode(PHP_EOL, $commands); } - return $commands; + $variables = ''; + foreach ($project->variables as $variable) { + $key = $variable->name; + $value = $variable->value; + + $variables .= "export {$key}={$value}" . PHP_EOL; + } + + return $variables . $commands; } /** diff --git a/app/ProjectRelation.php b/app/ProjectRelation.php index f04f502a0..bfe856308 100644 --- a/app/ProjectRelation.php +++ b/app/ProjectRelation.php @@ -70,6 +70,16 @@ public function commands() return $this->hasMany('REBELinBLUE\Deployer\Command')->orderBy('order', 'ASC'); } + /** + * Has many relationship. + * + * @return Variable + */ + public function variables() + { + return $this->hasMany('REBELinBLUE\Deployer\Variable'); + } + /** * Has many relationship. * diff --git a/app/Providers/RepositoryServiceProvider.php b/app/Providers/RepositoryServiceProvider.php index 98872faf6..87c9631e5 100644 --- a/app/Providers/RepositoryServiceProvider.php +++ b/app/Providers/RepositoryServiceProvider.php @@ -40,6 +40,7 @@ public function register() $this->bindInterface('SharedFile'); $this->bindInterface('Template'); $this->bindInterface('User'); + $this->bindInterface('Variable'); } /** diff --git a/app/Repositories/Contracts/VariableRepositoryInterface.php b/app/Repositories/Contracts/VariableRepositoryInterface.php new file mode 100644 index 000000000..0ea3bd2eb --- /dev/null +++ b/app/Repositories/Contracts/VariableRepositoryInterface.php @@ -0,0 +1,11 @@ +model = $model; + } +} diff --git a/app/Variable.php b/app/Variable.php new file mode 100644 index 000000000..847ee4944 --- /dev/null +++ b/app/Variable.php @@ -0,0 +1,39 @@ +belongsTo('REBELinBLUE\Deployer\Project'); + } +} diff --git a/composer.lock b/composer.lock index 4dc6ae415..2c638e2bf 100644 --- a/composer.lock +++ b/composer.lock @@ -264,33 +264,33 @@ }, { "name": "doctrine/cache", - "version": "v1.5.4", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/cache.git", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136" + "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/47cdc76ceb95cc591d9c79a36dc3794975b5d136", - "reference": "47cdc76ceb95cc591d9c79a36dc3794975b5d136", + "url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6", + "reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "~5.5|~7.0" }, "conflict": { "doctrine/common": ">2.2,<2.4" }, "require-dev": { - "phpunit/phpunit": ">=3.7", + "phpunit/phpunit": "~4.8|~5.0", "predis/predis": "~1.0", "satooshi/php-coveralls": "~0.6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.6.x-dev" } }, "autoload": { @@ -330,7 +330,7 @@ "cache", "caching" ], - "time": "2015-12-19 05:03:47" + "time": "2015-12-31 16:37:02" }, { "name": "doctrine/collections", @@ -473,16 +473,16 @@ }, { "name": "doctrine/dbal", - "version": "v2.5.3", + "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "2fbcea96eae34a53183377cdbb0b9bec33974648" + "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/2fbcea96eae34a53183377cdbb0b9bec33974648", - "reference": "2fbcea96eae34a53183377cdbb0b9bec33974648", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/abbdfd1cff43a7b99d027af3be709bc8fc7d4769", + "reference": "abbdfd1cff43a7b99d027af3be709bc8fc7d4769", "shasum": "" }, "require": { @@ -540,7 +540,7 @@ "persistence", "queryobject" ], - "time": "2015-12-25 16:28:24" + "time": "2016-01-05 22:11:12" }, { "name": "doctrine/inflector", @@ -966,16 +966,16 @@ }, { "name": "intervention/image", - "version": "2.3.4", + "version": "2.3.5", "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "a67ee32df0c6820cc6e861ad4144ee0ef9c74aa3" + "reference": "9f29360b8ab94585cb9e80cf9045abd5b85feb89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/a67ee32df0c6820cc6e861ad4144ee0ef9c74aa3", - "reference": "a67ee32df0c6820cc6e861ad4144ee0ef9c74aa3", + "url": "https://api.github.com/repos/Intervention/image/zipball/9f29360b8ab94585cb9e80cf9045abd5b85feb89", + "reference": "9f29360b8ab94585cb9e80cf9045abd5b85feb89", "shasum": "" }, "require": { @@ -1024,20 +1024,20 @@ "thumbnail", "watermark" ], - "time": "2015-11-30 17:03:21" + "time": "2016-01-02 19:15:13" }, { "name": "itsgoingd/clockwork", - "version": "v1.10", + "version": "v1.10.1", "source": { "type": "git", "url": "https://github.com/itsgoingd/clockwork.git", - "reference": "b3f0cd7f314d55ede9c70dda48425b7fb03d7ed6" + "reference": "f14f8e91a34efd0d17e8350a1db5d436154bec87" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b3f0cd7f314d55ede9c70dda48425b7fb03d7ed6", - "reference": "b3f0cd7f314d55ede9c70dda48425b7fb03d7ed6", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/f14f8e91a34efd0d17e8350a1db5d436154bec87", + "reference": "f14f8e91a34efd0d17e8350a1db5d436154bec87", "shasum": "" }, "require": { @@ -1069,7 +1069,7 @@ "logging", "profiling" ], - "time": "2015-12-23 12:31:51" + "time": "2016-01-07 15:13:57" }, { "name": "jakub-onderka/php-console-color", @@ -1218,16 +1218,16 @@ }, { "name": "laravel/framework", - "version": "v5.1.27", + "version": "v5.1.28", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "b16f80878fd3603022d3c84593397cedd9af0bcf" + "reference": "3f0fd27939dfdafb1e50058423cd24e640894ba2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/b16f80878fd3603022d3c84593397cedd9af0bcf", - "reference": "b16f80878fd3603022d3c84593397cedd9af0bcf", + "url": "https://api.github.com/repos/laravel/framework/zipball/3f0fd27939dfdafb1e50058423cd24e640894ba2", + "reference": "3f0fd27939dfdafb1e50058423cd24e640894ba2", "shasum": "" }, "require": { @@ -1342,7 +1342,7 @@ "framework", "laravel" ], - "time": "2015-12-17 20:35:38" + "time": "2015-12-31 17:41:30" }, { "name": "league/flysystem", @@ -1794,16 +1794,16 @@ }, { "name": "paragonie/random_compat", - "version": "1.1.4", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "d762ee5b099a29044603cd4649851e81aa66cb47" + "reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/d762ee5b099a29044603cd4649851e81aa66cb47", - "reference": "d762ee5b099a29044603cd4649851e81aa66cb47", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/dd8998b7c846f6909f4e7a5f67fabebfc412a4f7", + "reference": "dd8998b7c846f6909f4e7a5f67fabebfc412a4f7", "shasum": "" }, "require": { @@ -1838,7 +1838,7 @@ "pseudorandom", "random" ], - "time": "2015-12-10 14:48:13" + "time": "2016-01-06 13:31:20" }, { "name": "pda/pheanstalk", @@ -3711,27 +3711,26 @@ }, { "name": "pdepend/pdepend", - "version": "2.2.2", + "version": "2.2.0", "source": { "type": "git", "url": "https://github.com/pdepend/pdepend.git", - "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5" + "reference": "eceacb580af64e9039b274a1e9c6997fc69756c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/pdepend/pdepend/zipball/d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", - "reference": "d3ae0d084d526cdc6c3f1b858fb7148de77b41c5", + "url": "https://api.github.com/repos/pdepend/pdepend/zipball/eceacb580af64e9039b274a1e9c6997fc69756c7", + "reference": "eceacb580af64e9039b274a1e9c6997fc69756c7", "shasum": "" }, "require": { - "php": ">=5.3.7", - "symfony/config": "^2.3.0", - "symfony/dependency-injection": "^2.3.0", - "symfony/filesystem": "^2.3.0" + "symfony/config": ">=2.4", + "symfony/dependency-injection": ">=2.4", + "symfony/filesystem": ">=2.4" }, "require-dev": { - "phpunit/phpunit": "^4.0.0,<4.8", - "squizlabs/php_codesniffer": "^2.0.0" + "phpunit/phpunit": "4.*@stable", + "squizlabs/php_codesniffer": "@stable" }, "bin": [ "src/bin/pdepend" @@ -3747,7 +3746,7 @@ "BSD-3-Clause" ], "description": "Official version of pdepend to be handled with Composer", - "time": "2015-10-16 08:49:58" + "time": "2015-09-20 20:30:27" }, { "name": "phpdocumentor/reflection-docblock", @@ -4997,26 +4996,26 @@ }, { "name": "symfony/config", - "version": "v2.8.1", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "17d4b2e64ce1c6ba7caa040f14469b3c44d7f7d2" + "reference": "58680a6516a457a6c65044fe33586c4a81fdff01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/17d4b2e64ce1c6ba7caa040f14469b3c44d7f7d2", - "reference": "17d4b2e64ce1c6ba7caa040f14469b3c44d7f7d2", + "url": "https://api.github.com/repos/symfony/config/zipball/58680a6516a457a6c65044fe33586c4a81fdff01", + "reference": "58680a6516a457a6c65044fe33586c4a81fdff01", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/filesystem": "~2.3|~3.0.0" + "php": ">=5.5.9", + "symfony/filesystem": "~2.8|~3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -5043,32 +5042,29 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2015-12-26 13:37:56" + "time": "2015-12-26 13:39:53" }, { "name": "symfony/dependency-injection", - "version": "v2.8.1", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "c5086d186f538c2711b9af6f727be7b0446979cd" + "reference": "1256a2e57879ae561278c306d47977d1f73387b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c5086d186f538c2711b9af6f727be7b0446979cd", - "reference": "c5086d186f538c2711b9af6f727be7b0446979cd", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/1256a2e57879ae561278c306d47977d1f73387b8", + "reference": "1256a2e57879ae561278c306d47977d1f73387b8", "shasum": "" }, "require": { - "php": ">=5.3.9" - }, - "conflict": { - "symfony/expression-language": "<2.6" + "php": ">=5.5.9" }, "require-dev": { - "symfony/config": "~2.2|~3.0.0", - "symfony/expression-language": "~2.6|~3.0.0", - "symfony/yaml": "~2.1|~3.0.0" + "symfony/config": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/yaml": "~2.8|~3.0" }, "suggest": { "symfony/config": "", @@ -5078,7 +5074,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -5105,29 +5101,29 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", - "time": "2015-12-26 13:37:56" + "time": "2015-12-26 13:39:53" }, { "name": "symfony/filesystem", - "version": "v2.8.1", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "a7ad724530a764d70c168d321ac226ba3d2f10fc" + "reference": "c2e59d11dccd135dc8f00ee97f34fe1de842e70c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/a7ad724530a764d70c168d321ac226ba3d2f10fc", - "reference": "a7ad724530a764d70c168d321ac226ba3d2f10fc", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c2e59d11dccd135dc8f00ee97f34fe1de842e70c", + "reference": "c2e59d11dccd135dc8f00ee97f34fe1de842e70c", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -5154,7 +5150,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-12-22 10:25:57" + "time": "2015-12-22 10:39:06" }, { "name": "symfony/stopwatch", diff --git a/database/migrations/2015_12_31_144850_create_variables_table.php b/database/migrations/2015_12_31_144850_create_variables_table.php new file mode 100644 index 000000000..74a1b0bd7 --- /dev/null +++ b/database/migrations/2015_12_31_144850_create_variables_table.php @@ -0,0 +1,35 @@ +increments('id'); + $table->string('name'); + $table->string('value'); + $table->unsignedInteger('project_id'); + $table->timestamps(); + $table->softDeletes(); + $table->foreign('project_id')->references('id')->on('projects'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('variables'); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 3445fad69..b786f95a9 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -22,5 +22,6 @@ public function run() $this->call('NotificationTableSeeder'); $this->call('HeartbeatTableSeeder'); $this->call('TemplateSeeder'); + $this->call('VariableTableSeeder'); } } diff --git a/database/seeds/VariableTableSeeder.php b/database/seeds/VariableTableSeeder.php new file mode 100644 index 000000000..df85cf39e --- /dev/null +++ b/database/seeds/VariableTableSeeder.php @@ -0,0 +1,18 @@ +delete(); + + Variable::create([ + 'project_id' => 1, + 'name' => 'COMPOSER_PROCESS_TIMEOUT', + 'value' => '3000' + ]); + } +} diff --git a/gulpfile.js b/gulpfile.js index bdc8f91e7..15a225db0 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -68,6 +68,7 @@ elixir(function(mix) { 'shareFiles.js', 'projectFiles.js', 'checkUrls.js', + 'variables.js', 'deployment.js', 'commands.js', 'users.js', diff --git a/resources/assets/js/variables.js b/resources/assets/js/variables.js new file mode 100644 index 000000000..56c1f29d7 --- /dev/null +++ b/resources/assets/js/variables.js @@ -0,0 +1,215 @@ +var app = app || {}; + +(function ($) { + // FIXME: This seems very wrong + $('#variable').on('show.bs.modal', function (event) { + var button = $(event.relatedTarget); + var modal = $(this); + var title = Lang.variables.create; + + $('.btn-danger', modal).hide(); + $('.callout-danger', modal).hide(); + $('.has-error', modal).removeClass('has-error'); + $('.label-danger', modal).remove(); + + if (button.hasClass('btn-edit')) { + title = Lang.variables.edit; + $('.btn-danger', modal).show(); + } else { + $('#variable_id').val(''); + $('#variable_name').val(''); + $('#variable_value').val(''); + } + + modal.find('.modal-title span').text(title); + }); + + // FIXME: This seems very wrong + $('#variable button.btn-delete').on('click', function (event) { + var target = $(event.currentTarget); + var icon = target.find('i'); + var dialog = target.parents('.modal'); + + icon.addClass('fa-refresh fa-spin').removeClass('fa-trash'); + dialog.find('input').attr('disabled', 'disabled'); + $('button.close', dialog).hide(); + + var variable = app.Variables.get($('#variable_id').val()); + + variable.destroy({ + wait: true, + success: function(model, response, options) { + dialog.modal('hide'); + $('.callout-danger', dialog).hide(); + + icon.removeClass('fa-refresh fa-spin').addClass('fa-trash'); + $('button.close', dialog).show(); + dialog.find('input').removeAttr('disabled'); + }, + error: function() { + icon.removeClass('fa-refresh fa-spin').addClass('fa-trash'); + $('button.close', dialog).show(); + dialog.find('input').removeAttr('disabled'); + } + }); + }); + + // FIXME: This seems very wrong + $('#variable button.btn-save').on('click', function (event) { + var target = $(event.currentTarget); + var icon = target.find('i'); + var dialog = target.parents('.modal'); + + icon.addClass('fa-refresh fa-spin').removeClass('fa-save'); + dialog.find('input').attr('disabled', 'disabled'); + $('button.close', dialog).hide(); + + var variable_id = $('#variable_id').val(); + + if (variable_id) { + var variable = app.Variables.get(variable_id); + } else { + var variable = new app.Variable(); + } + + variable.save({ + name: $('#variable_name').val(), + value: $('#variable_value').val(), + project_id: $('input[name="project_id"]').val(), + }, { + wait: true, + success: function(model, response, options) { + dialog.modal('hide'); + $('.callout-danger', dialog).hide(); + + icon.removeClass('fa-refresh fa-spin').addClass('fa-save'); + $('button.close', dialog).show(); + dialog.find('input').removeAttr('disabled'); + + if (!variable_id) { + app.Variables.add(response); + } + }, + error: function(model, response, options) { + $('.callout-danger', dialog).show(); + + var errors = response.responseJSON; + + $('.has-error', dialog).removeClass('has-error'); + $('.label-danger', dialog).remove(); + + $('form input', dialog).each(function (index, element) { + element = $(element); + + var name = element.attr('name'); + + if (typeof errors[name] !== 'undefined') { + var parent = element.parent('div'); + parent.addClass('has-error'); + parent.append($('').attr('class', 'label label-danger').text(errors[name])); + } + }); + + icon.removeClass('fa-refresh fa-spin').addClass('fa-save'); + $('button.close', dialog).show(); + dialog.find('input').removeAttr('disabled'); + } + }); + }); + + app.Variable = Backbone.Model.extend({ + urlRoot: '/variables', + initialize: function() { + + } + }); + + var Variables = Backbone.Collection.extend({ + model: app.Variable + }); + + app.Variables = new Variables(); + + app.VariablesTab = Backbone.View.extend({ + el: '#app', + events: { + + }, + initialize: function() { + this.$list = $('#variable_list tbody'); + + $('#variable_list').hide(); + + this.listenTo(app.Variables, 'add', this.addOne); + this.listenTo(app.Variables, 'reset', this.addAll); + this.listenTo(app.Variables, 'remove', this.addAll); + this.listenTo(app.Variables, 'all', this.render); + + app.listener.on('variable:REBELinBLUE\\Deployer\\Events\\ModelChanged', function (data) { + $('#variable_' + data.model.id).html(data.model.name); + + var variable = app.Variables.get(parseInt(data.model.id)); + + if (variable) { + variable.set(data.model); + } + }); + + app.listener.on('variable:REBELinBLUE\\Deployer\\Events\\ModelCreated', function (data) { + app.Variables.add(data.model); + }); + + app.listener.on('variable:REBELinBLUE\\Deployer\\Events\\ModelTrashed', function (data) { + var variable = app.Variables.get(parseInt(data.model.id)); + + if (variable) { + app.Variables.remove(variable); + } + }); + }, + render: function () { + if (app.Variables.length) { + $('#variable_list').show(); + } else { + $('#variable_list').hide(); + } + }, + addOne: function (variable) { + + var view = new app.VariableView({ + model: variable + }); + + this.$list.append(view.render().el); + }, + addAll: function () { + this.$list.html(''); + app.Variables.each(this.addOne, this); + } + }); + + app.VariableView = Backbone.View.extend({ + tagName: 'tr', + events: { + 'click .btn-edit': 'editVariable' + }, + initialize: function () { + this.listenTo(this.model, 'change', this.render); + this.listenTo(this.model, 'destroy', this.remove); + + this.template = _.template($('#variable-template').html()); + }, + render: function () { + var data = this.model.toJSON(); + + this.$el.html(this.template(data)); + + return this; + }, + editVariable: function() { + $('#variable_id').val(this.model.id); + $('#variable_name').val(this.model.get('name')); + $('#variable_value').val(this.model.get('value')); + } + }); +})(jQuery); \ No newline at end of file diff --git a/resources/lang/en/auth.php b/resources/lang/en/auth.php index 9b156934b..f9a5e7f2e 100644 --- a/resources/lang/en/auth.php +++ b/resources/lang/en/auth.php @@ -1,4 +1,3 @@ - 'URL tests', + 'label' => 'URL Tests', 'create' => 'Add a new URL', 'edit' => 'Edit the URL', 'none' => 'You can add URLs which should be requested periodically and after a deployment has finished.', diff --git a/resources/lang/en/variables.php b/resources/lang/en/variables.php new file mode 100644 index 000000000..14bbfe28c --- /dev/null +++ b/resources/lang/en/variables.php @@ -0,0 +1,16 @@ + 'Environment Variables', + 'create' => 'Add a new variable', + 'edit' => 'Edit the variable', + 'name' => 'Variable', + 'value' => 'Value', + 'warning' => 'The variable could not be saved, please check the form below.', + 'description' => 'Sometimes you need may need certain environmental variables defined during a deployment ' . + 'but you do not want to set them in the ~/.bashrc file on the server.', + 'example' => 'For example, you may want to set COMPOSER_PROCESS_TIMEOUT to allow composer ' . + 'to run for longer, or SYMFONY_ENV if you are deploying a symfony project.', + +]; diff --git a/resources/views/dialogs/variable.blade.php b/resources/views/dialogs/variable.blade.php new file mode 100644 index 000000000..49af52051 --- /dev/null +++ b/resources/views/dialogs/variable.blade.php @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/resources/views/projects/_partials/variables.blade.php b/resources/views/projects/_partials/variables.blade.php new file mode 100644 index 000000000..0f427ee6c --- /dev/null +++ b/resources/views/projects/_partials/variables.blade.php @@ -0,0 +1,44 @@ +
+
+
+ +
+

{{ Lang::get('variables.label') }}

+
+
+

{!! Lang::get('variables.description') !!}

+

{!! Lang::get('variables.example') !!}

+
+ +
+ + + + + + + + + + + +
{{ Lang::get('variables.name') }}{{ Lang::get('variables.value') }} 
+
+
+ + + + \ No newline at end of file diff --git a/resources/views/projects/details.blade.php b/resources/views/projects/details.blade.php index 38d2ac766..df3cbb0a0 100644 --- a/resources/views/projects/details.blade.php +++ b/resources/views/projects/details.blade.php @@ -72,6 +72,7 @@
@include('projects._partials.commands') + @include('projects._partials.variables')
@include('projects._partials.shared_files') @@ -94,6 +95,7 @@ @include('dialogs.project_files') @include('dialogs.channel') @include('dialogs.webhook') + @include('dialogs.variable') @include('dialogs.notify_email') @include('dialogs.heartbeat') @include('dialogs.check_urls') @@ -109,6 +111,7 @@ new app.NotificationsTab(); new app.NotifyEmailsTab(); new app.HeartbeatsTab(); + new app.VariablesTab(); new app.CheckUrlsTab(); app.Servers.add({!! $servers->toJson() !!}); @@ -118,6 +121,7 @@ app.NotifyEmails.add({!! $notifyEmails->toJson() !!}); app.Heartbeats.add({!! $heartbeats->toJson() !!}); app.CheckUrls.add({!! $checkUrls->toJson() !!}); + app.Variables.add({!! $variables->toJson() !!}); app.project_id = {{ $project->id }};