Improve UI, add Names to things

- Document some more
- Add names to Repository/environment/inventory
- UI for new Template
This commit is contained in:
Matej Kramny 2016-04-11 11:02:10 +01:00
parent a9011c3c64
commit 990f1e7f90
20 changed files with 208 additions and 28 deletions

View File

@ -0,0 +1,3 @@
alter table project__environment add `name` varchar(255) not null;
alter table project__inventory add `name` varchar(255) not null;
alter table project__repository add `name` varchar(255) not null;

View File

@ -57,5 +57,7 @@ func init() {
{},
{Major: 1},
{Major: 1, Minor: 1},
{Major: 1, Minor: 2},
{Major: 1, Minor: 3},
}
}

View File

@ -4,9 +4,10 @@ import "github.com/ansible-semaphore/semaphore/database"
type Environment struct {
ID int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required"`
ProjectID int `db:"project_id" json:"project_id"`
Password *string `db:"password" json:"password"`
JSON string `db:"json" json:"json"`
JSON string `db:"json" json:"json" binding:"required"`
}
func init() {

View File

@ -4,6 +4,7 @@ import "github.com/ansible-semaphore/semaphore/database"
type Inventory struct {
ID int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required"`
ProjectID int `db:"project_id" json:"project_id"`
Inventory string `db:"inventory" json:"inventory"`

View File

@ -4,6 +4,7 @@ import "github.com/ansible-semaphore/semaphore/database"
type Repository struct {
ID int `db:"id" json:"id"`
Name string `db:"name" json:"name" binding:"required"`
ProjectID int `db:"project_id" json:"project_id"`
GitUrl string `db:"git_url" json:"git_url" binding:"required"`
SshKeyID int `db:"ssh_key_id" json:"ssh_key_id" binding:"required"`

View File

@ -17,8 +17,8 @@ html(lang="en" ng-app="semaphore")
ul.nav.navbar-nav
li(ng-class="{ active: $state.includes('dashboard') }")
a(ui-sref="dashboard") Dashboard
li(ng-class="{ active: $state.includes('keys') }")
a(ui-sref="keys") Key Store
//- li(ng-class="{ active: $state.includes('keys') }")
//- a(ui-sref="keys") Key Store
li(ng-class="{ active: $state.includes('users') }")
a(ui-sref="users") Users

View File

@ -2,4 +2,4 @@ h3 Environment
table.table
tbody: tr(ng-repeat="env in environment")
td {{ env.id }}
td {{ env.name }}

View File

@ -2,4 +2,4 @@ h3 Inventory
table.table
tbody: tr(ng-repeat="inv in inventory")
td {{ inv.id }} - {{ inv.type }}
td {{ inv.name }} - {{ inv.type }}

View File

@ -1,12 +1,12 @@
h3 Keys
button.btn.btn-default.pull-right(ng-click="add()") Create Key
button.btn.btn-success.btn-xs.pull-right(ng-click="add()") Create Key
table.table
thead: tr
th Name
th Type
th Key
th.col-sm-2 Name
th.col-sm-2 Type
th.col-sm-8 Key
tbody: tr(ng-repeat="key in keys")
td {{ key.name }}
td {{ key.type }}
td {{ key.key }}
td: code {{ key.type }}
td: pre: code {{ key.key }}

View File

@ -1,5 +0,0 @@
h3 Repositories
table.table
tbody: tr(ng-repeat="repo in repositories")
td {{ repo.id }} - {{ repo.git_url }}

View File

@ -0,0 +1,20 @@
.modal-header
h4.modal-title Create Repository
.modal-body
form.form-horizontal
.form-group
label.control-label.col-sm-4 Name
.col-sm-6
input.form-control(type="text" ng-model="repo.name" placeholder="Friendly Repository Name")
.form-group
label.control-label.col-sm-4 Repository
.col-sm-6
input.form-control(type="text" ng-model="repo.git_url" placeholder="git@github.com:user/repo.git")
.form-group
label.control-label.col-sm-4 SSH Key
.col-sm-6
select.form-control(ng-model="repo.ssh_key_id" ng-options="key.id as key.name for key in keys")
option(value="") -- Select SSH Key --
.modal-footer
button.btn.btn-default.pull-left(ng-click="$dismiss()") Dismiss
button.btn.btn-success(ng-click="$close(repo)") Create

View File

@ -0,0 +1,14 @@
h3 Repositories
button.btn.btn-success.btn-xs.pull-right(ng-click="add()") Create Repository
table.table
thead: tr
th Name
th Git URL
th SSH Key
th  
tbody: tr(ng-repeat="repo in repositories")
td {{ repo.name }}
td {{ repo.git_url }}
td {{ repo.ssh_key_id }}
td: button.btn.btn-danger.btn-xs.pull-right(ng-click="remove(repo)") delete

View File

@ -1,5 +0,0 @@
h3 Task Templates
table.table
tbody: tr(ng-repeat="tpl in templates")
td {{ tpl.id }} - {{ tpl.playbook }}

View File

@ -0,0 +1,45 @@
.modal-header
h4.modal-title New Template
.modal-body
form.form-horizontal
.form-group
label.control-label.col-sm-4 Playbook Name
.col-sm-6
input.form-control(type="text" placeholder="play.yml" ng-model="tpl.playbook")
.form-group
label.control-label.col-sm-4 SSH Key
.col-sm-6
select.form-control(ng-model="tpl.ssh_key_id" ng-options="key.id as key.name for key in keys")
option(value="") -- Select SSH Key --
.form-group
label.control-label.col-sm-4 Inventory
.col-sm-6
select.form-control(ng-model="tpl.inventory_id" ng-options="inv.id as inv.name for inv in inventory")
option(value="") -- Select Inventory --
.form-group
label.control-label.col-sm-4 Playbook Repository
.col-sm-6
select.form-control(ng-model="tpl.repository_id" ng-options="repo.id as repo.name for repo in repositories")
option(value="") -- Select Playbook Repository --
.form-group
label.control-label.col-sm-4 Environment
.col-sm-6
select.form-control(ng-model="tpl.environment_id" ng-options="env.id as env.name for env in environment")
option(value="") -- Select Task Environment --
hr
.form-group
label.control-label.col-sm-4 Extra CLI Arguments
.col-sm-6
textarea.form-control(placeholder='*MUST* be a JSON array! Each argument must be an element of the array, for example: ["-i", "@myinventory.sh", "--private-key=/there/id_rsa", "-vvvv"]' ng-model="tpl.arguments" rows="5")
.form-group
.col-sm-6.col-sm-offset-4
.checkbox: label
input(type="checkbox" ng-model="user.admin")
| Override semaphore arguments
p.help-block Usually semaphore prepends arguments like `--private-key=/location/id_rsa` to make sure everything goes smoothly. This option is for special needs, where semaphore conflicts with one of your arguments.
.modal-footer
button.btn.btn-default.pull-left(ng-click="$dismiss()") Dismiss
button.btn.btn-success(ng-click="$close(user)") Create

View File

@ -0,0 +1,16 @@
h3 Task Templates
button.btn.btn-success.btn-xs.pull-right(ng-click="add()") New Template
table.table
thead: tr
th Playbook
th SSH Key
th Inventory
th Environment
th Repository
tbody: tr(ng-repeat="tpl in templates")
td {{ tpl.playbook }}
td {{ sshKeysAssoc[tpl.ssh_key_id].name }}
td {{ inventoryAssoc[tpl.inventory_id].name }}
td {{ environmentAssoc[tpl.environment_id].name }}
td {{ reposAssoc[tpl.repository_id].name }}

View File

@ -1,8 +1,8 @@
define(function () {
app.registerController('ProjectRepositoriesCtrl', ['$scope', '$http', '$uibModal', 'Project', function ($scope, $http, $modal, Project) {
app.registerController('ProjectRepositoriesCtrl', ['$scope', '$http', 'Project', '$uibModal', '$rootScope', function ($scope, $http, Project, $modal, $rootScope) {
$scope.reload = function () {
$http.get(Project.getURL() + '/repositories').success(function (repositories) {
$scope.repositories = repositories;
$http.get(Project.getURL() + '/repositories').success(function (repos) {
$scope.repositories = repos;
});
}
@ -14,6 +14,25 @@ define(function () {
});
}
$scope.add = function () {
$http.get(Project.getURL() + '/keys?type=ssh').success(function (keys) {
var scope = $rootScope.$new();
scope.keys = keys;
$modal.open({
templateUrl: '/tpl/projects/repositories/add.html',
scope: scope
}).result.then(function (repo) {
$http.post(Project.getURL() + '/repositories', repo)
.success(function () {
$scope.reload();
}).error(function (_, status) {
swal('Erorr', 'Repository not added: ' + status, 'error');
});
});
});
}
$scope.reload();
}]);
});

View File

@ -1,5 +1,38 @@
define(function () {
app.registerController('ProjectTemplatesCtrl', ['$scope', '$http', '$uibModal', 'Project', function ($scope, $http, $modal, Project) {
app.registerController('ProjectTemplatesCtrl', ['$scope', '$http', '$uibModal', 'Project', '$rootScope', function ($scope, $http, $modal, Project, $rootScope) {
$http.get(Project.getURL() + '/keys?type=ssh').success(function (keys) {
$scope.sshKeys = keys;
$scope.sshKeysAssoc = {};
keys.forEach(function (k) {
$scope.sshKeysAssoc[k.id] = k;
});
});
$http.get(Project.getURL() + '/inventory').success(function (inv) {
$scope.inventory = inv;
$scope.inventoryAssoc = {};
inv.forEach(function (i) {
$scope.inventoryAssoc[i.id] = i;
});
});
$http.get(Project.getURL() + '/repositories').success(function (repos) {
$scope.repos = repos;
$scope.reposAssoc = {};
repos.forEach(function (i) {
$scope.reposAssoc[i.id] = i;
});
});
$http.get(Project.getURL() + '/environment').success(function (env) {
$scope.environment = env;
$scope.environmentAssoc = {};
env.forEach(function (i) {
$scope.environmentAssoc[i.id] = i;
});
});
$scope.reload = function () {
$http.get(Project.getURL() + '/templates').success(function (templates) {
$scope.templates = templates;
@ -14,6 +47,25 @@ define(function () {
});
}
$scope.add = function () {
var scope = $rootScope.$new();
scope.keys = $scope.sshKeys;
scope.inventory = $scope.inventory;
scope.repositories = $scope.repos;
scope.environment = $scope.environment;
$modal.open({
templateUrl: '/tpl/projects/templates/add.html',
scope: scope
}).result.then(function (tpl) {
$http.post(Project.getURL() + '/templates', tpl).success(function () {
$scope.reload();
}).error(function (_, status) {
swal('error', 'could not add template:' + status, 'error');
});
});
}
$scope.reload();
}]);
});

View File

@ -45,7 +45,7 @@ app.config(function ($stateProvider, $couchPotatoProvider) {
.state('project.templates', {
url: '/templates',
pageTitle: 'Templates',
templateUrl: '/tpl/projects/templates.html',
templateUrl: '/tpl/projects/templates/list.html',
controller: 'ProjectTemplatesCtrl',
resolve: {
$d: $couchPotatoProvider.resolveDependencies(['controllers/projects/templates'])
@ -85,7 +85,7 @@ app.config(function ($stateProvider, $couchPotatoProvider) {
.state('project.repositories', {
url: '/repositories',
pageTitle: 'Repositories',
templateUrl: '/tpl/projects/repositories.html',
templateUrl: '/tpl/projects/repositories/list.html',
controller: 'ProjectRepositoriesCtrl',
resolve: {
$d: $couchPotatoProvider.resolveDependencies(['controllers/projects/repositories'])

View File

@ -50,7 +50,10 @@ func GetRepositories(c *gin.Context) {
func AddRepository(c *gin.Context) {
project := c.MustGet("project").(models.Project)
var repository models.Repository
var repository struct {
GitUrl string `json:"git_url" binding:"required"`
SshKeyID int `json:"ssh_key_id" binding:"required"`
}
if err := c.Bind(&repository); err != nil {
return
}

View File

@ -95,6 +95,8 @@ definitions:
properties:
id:
type: integer
name:
type: string
project_id:
type: integer
password:
@ -106,6 +108,8 @@ definitions:
properties:
id:
type: integer
name:
type: string
project_id:
type: integer
inventory:
@ -121,6 +125,8 @@ definitions:
properties:
id:
type: integer
name:
type: string
project_id:
type: integer
git_url:
@ -430,6 +436,13 @@ paths:
tags:
- project
summary: Get access keys linked to project
parameters:
- name: Key type
in: query
required: false
type: string
format: ssh/aws/gcloud/do
description: Filter by key type
responses:
200:
description: Access Keys