Merge branch 'ps-env-vars'
Conflicts: assets/scripts/app/controllers.coffee assets/scripts/app/helpers/handlebars.coffee assets/scripts/app/templates/repo/settings.hbs assets/scripts/app/views/repo/show.coffee assets/styles/tabs.sass config.ru
This commit is contained in:
commit
9741ede075
29
assets/images/ui/bubbles-spinner.svg
Normal file
29
assets/images/ui/bubbles-spinner.svg
Normal file
|
@ -0,0 +1,29 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="64" height="64" fill="white">
|
||||
<circle cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(45 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.125s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(90 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.25s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(135 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.375s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(225 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.625s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(270 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.75s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(315 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.875s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
<circle transform="rotate(180 16 16)" cx="16" cy="3" r="0">
|
||||
<animate attributeName="r" values="0;3;0;0" dur="1s" repeatCount="indefinite" begin="0.5s" keySplines="0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8;0.2 0.2 0.4 0.8" calcMode="spline" />
|
||||
</circle>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/images/ui/secure.png
Normal file
BIN
assets/images/ui/secure.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 371 B |
|
@ -22,10 +22,13 @@ unless window.TravisApplication
|
|||
annotations: Travis.Annotation
|
||||
request: Travis.Request
|
||||
requests: Travis.Request
|
||||
env_var: Travis.EnvVar
|
||||
env_vars: Travis.EnvVar
|
||||
ssh_key: Travis.SshKey
|
||||
).property()
|
||||
|
||||
modelClasses: (->
|
||||
[Travis.User, Travis.Build, Travis.Job, Travis.Repo, Travis.Commit, Travis.Worker, Travis.Account, Travis.Broadcast, Travis.Hook, Travis.Annotation, Travis.Request]
|
||||
[Travis.User, Travis.Build, Travis.Job, Travis.Repo, Travis.Commit, Travis.Worker, Travis.Account, Travis.Broadcast, Travis.Hook, Travis.Annotation, Travis.Request, Travis.EnvVar, Travis.SshKey]
|
||||
).property()
|
||||
|
||||
setup: ->
|
||||
|
@ -33,6 +36,12 @@ unless window.TravisApplication
|
|||
klass.adapter = Travis.Adapter.create()
|
||||
klass.url = "/#{klass.pluralName()}"
|
||||
|
||||
Travis.EnvVar.url = "/settings/env_vars"
|
||||
Travis.EnvVar.adapter = Travis.EnvVarsAdapter.create()
|
||||
|
||||
Travis.SshKey.url = "/settings/ssh_key"
|
||||
Travis.SshKey.adapter = Travis.SshKeyAdapter.create()
|
||||
|
||||
@slider = new Travis.Slider()
|
||||
@pusher = new Travis.Pusher(Travis.config.pusher_key) if Travis.config.pusher_key
|
||||
@tailing = new Travis.Tailing($(window), '#tail', '#log')
|
||||
|
|
|
@ -50,27 +50,6 @@ Travis.FirstSyncController = Em.Controller.extend
|
|||
|
||||
Travis.IndexErrorController = Em.Controller.extend()
|
||||
|
||||
Travis.RepoSettingsTabController = Em.ObjectController.extend()
|
||||
Travis.RepoSettingsController = Em.ObjectController.extend
|
||||
needs: ['repoSettingsTab']
|
||||
tab: Ember.computed.alias('controllers.repoSettingsTab.model.tab')
|
||||
settings: Ember.computed.alias('model.settings')
|
||||
|
||||
settingsChanged: (->
|
||||
value = @get('settings.maximum_number_of_builds')
|
||||
console.log value
|
||||
if parseInt(value) > 0 || value == '0' || value == 0
|
||||
@set('settings.maximum_number_of_builds_valid', '')
|
||||
@get('model').saveSettings(@get('settings')).then null, ->
|
||||
Travis.flash(error: 'There was an error while saving settings. Please try again.')
|
||||
else
|
||||
@set('settings.maximum_number_of_builds_valid', 'invalid')
|
||||
).observes('settings.maximum_number_of_builds')
|
||||
|
||||
save: ->
|
||||
@get('model').saveSettings(@get('settings')).then null, ->
|
||||
Travis.flash(error: 'There was an error while saving settings. Please try again.')
|
||||
|
||||
require 'controllers/accounts'
|
||||
require 'controllers/auth'
|
||||
require 'controllers/account'
|
||||
|
@ -82,8 +61,13 @@ require 'controllers/job'
|
|||
require 'controllers/profile'
|
||||
require 'controllers/repos'
|
||||
require 'controllers/repo'
|
||||
require 'controllers/repo_settings'
|
||||
require 'controllers/stats'
|
||||
require 'controllers/current_user'
|
||||
require 'controllers/request'
|
||||
require 'controllers/requests'
|
||||
require 'controllers/caches'
|
||||
require 'controllers/env_var'
|
||||
require 'controllers/env_vars'
|
||||
require 'controllers/env_var_new'
|
||||
require 'controllers/ssh_key'
|
||||
|
|
52
assets/scripts/app/controllers/env_var.coffee
Normal file
52
assets/scripts/app/controllers/env_var.coffee
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'travis/validations'
|
||||
|
||||
Travis.EnvVarController = Ember.ObjectController.extend Travis.Validations,
|
||||
isEditing: false
|
||||
isDeleting: false
|
||||
|
||||
validates:
|
||||
name: ['presence']
|
||||
|
||||
actionType: 'Save'
|
||||
showValueField: Ember.computed.alias('public')
|
||||
|
||||
value: ( (key, value) ->
|
||||
if arguments.length == 2
|
||||
@get('model').set('value', value)
|
||||
value
|
||||
else if @get('public')
|
||||
@get('model.value')
|
||||
else
|
||||
'••••••••••••••••'
|
||||
).property('model.value', 'public')
|
||||
|
||||
actions:
|
||||
delete: ->
|
||||
return if @get('isDeleting')
|
||||
@set('isDeleting', true)
|
||||
|
||||
deletingDone = => @set('isDeleting', false)
|
||||
@get('model').deleteRecord().then deletingDone, deletingDone
|
||||
|
||||
edit: ->
|
||||
@set('isEditing', true)
|
||||
|
||||
cancel: ->
|
||||
@set('isEditing', false)
|
||||
@get('model').revert()
|
||||
|
||||
save: ->
|
||||
return if @get('isSaving')
|
||||
@set('isSaving', true)
|
||||
|
||||
if @isValid()
|
||||
env_var = @get('model')
|
||||
|
||||
# TODO: handle errors
|
||||
env_var.save().then =>
|
||||
@set('isEditing', false)
|
||||
@set('isSaving', false)
|
||||
, =>
|
||||
@set('isSaving', false)
|
||||
else
|
||||
@set('isSaving', false)
|
41
assets/scripts/app/controllers/env_var_new.coffee
Normal file
41
assets/scripts/app/controllers/env_var_new.coffee
Normal file
|
@ -0,0 +1,41 @@
|
|||
require 'travis/validations'
|
||||
|
||||
Travis.EnvVarsNewController = Travis.Controller.extend Travis.Validations,
|
||||
needs: ['repo']
|
||||
repo: Ember.computed.alias('controllers.repo.repo')
|
||||
|
||||
validates:
|
||||
name: ['presence']
|
||||
|
||||
actionType: 'Add'
|
||||
showValueField: true
|
||||
|
||||
reset: ->
|
||||
@setProperties(name: null, value: null, public: null)
|
||||
|
||||
actions:
|
||||
cancel: ->
|
||||
@reset()
|
||||
@transitionToRoute('env_vars')
|
||||
|
||||
save: ->
|
||||
return if @get('isSaving')
|
||||
@set('isSaving', true)
|
||||
|
||||
if @isValid()
|
||||
env_var = Travis.EnvVar.create(
|
||||
name: @get('name')
|
||||
value: @get('value')
|
||||
public: @get('public')
|
||||
repo: @get('repo')
|
||||
)
|
||||
|
||||
self = this
|
||||
env_var.save().then =>
|
||||
@set('isSaving', false)
|
||||
@reset()
|
||||
self.transitionToRoute('env_vars')
|
||||
, =>
|
||||
@set('isSaving', false)
|
||||
else
|
||||
@set('isSaving', false)
|
1
assets/scripts/app/controllers/env_vars.coffee
Normal file
1
assets/scripts/app/controllers/env_vars.coffee
Normal file
|
@ -0,0 +1 @@
|
|||
Travis.EnvVarsController = Ember.ArrayController.extend()
|
|
@ -59,6 +59,9 @@ Travis.RepoController = Travis.Controller.extend
|
|||
viewRequest: ->
|
||||
@connectTab('request')
|
||||
|
||||
viewSettings: ->
|
||||
@connectTab('settings')
|
||||
|
||||
lastBuildDidChange: ->
|
||||
Ember.run.scheduleOnce('data', this, @_lastBuildDidChange);
|
||||
|
||||
|
|
30
assets/scripts/app/controllers/repo_settings.coffee
Normal file
30
assets/scripts/app/controllers/repo_settings.coffee
Normal file
|
@ -0,0 +1,30 @@
|
|||
Travis.RepoSettingsController = Em.ObjectController.extend
|
||||
tabs:
|
||||
index: "General Settings"
|
||||
env_vars: "Environment Variables"
|
||||
ssh_key: "SSH Key"
|
||||
|
||||
init: ->
|
||||
@_super.apply this, arguments
|
||||
|
||||
tabs = []
|
||||
@set('_tabs', tabs)
|
||||
for own id, name of @get('tabs')
|
||||
tabs.pushObject Travis.Tab.create(id: id, name: name)
|
||||
|
||||
settings: Ember.computed.alias('model.settings')
|
||||
|
||||
settingsChanged: (->
|
||||
value = @get('settings.maximum_number_of_builds')
|
||||
console.log value
|
||||
if parseInt(value) > 0 || value == '0' || value == 0
|
||||
@set('settings.maximum_number_of_builds_valid', '')
|
||||
@get('model').saveSettings(@get('settings')).then null, ->
|
||||
Travis.flash(error: 'There was an error while saving settings. Please try again.')
|
||||
else
|
||||
@set('settings.maximum_number_of_builds_valid', 'invalid')
|
||||
).observes('settings.maximum_number_of_builds')
|
||||
|
||||
save: ->
|
||||
@get('model').saveSettings(@get('settings')).then null, ->
|
||||
Travis.flash(error: 'There was an error while saving settings. Please try again.')
|
51
assets/scripts/app/controllers/ssh_key.coffee
Normal file
51
assets/scripts/app/controllers/ssh_key.coffee
Normal file
|
@ -0,0 +1,51 @@
|
|||
require 'travis/validations'
|
||||
|
||||
Travis.SshKeyController = Ember.ObjectController.extend Travis.Validations,
|
||||
isEditing: false
|
||||
isSaving: false
|
||||
isDeleting: false
|
||||
defaultKey: null
|
||||
|
||||
needs: ['repo']
|
||||
repo: Ember.computed.alias('controllers.repo.repo')
|
||||
|
||||
validates:
|
||||
value: ['presence']
|
||||
|
||||
actions:
|
||||
add: ->
|
||||
model = Travis.SshKey.create(id: @get('repo.id'))
|
||||
@set('model', model)
|
||||
@set('isEditing', true)
|
||||
|
||||
save: ->
|
||||
return if @get('isSaving')
|
||||
@set('isSaving', true)
|
||||
|
||||
if @isValid()
|
||||
@get('model').save().then =>
|
||||
@set('isEditing', false)
|
||||
@set('isSaving', false)
|
||||
, (xhr) =>
|
||||
@set('isSaving', false)
|
||||
if xhr.status == 422
|
||||
@addErrorsFromResponse(JSON.parse(xhr.response)['errors'])
|
||||
else
|
||||
@set('isSaving', false)
|
||||
|
||||
delete: ->
|
||||
return if @get('isDeleting')
|
||||
@set('isDeleting', true)
|
||||
|
||||
deletingDone = => @set('isDeleting', false)
|
||||
@get('model').deleteRecord().then(deletingDone, deletingDone).then =>
|
||||
@set('model', null)
|
||||
|
||||
cancel: ->
|
||||
if model = @get('model')
|
||||
if model.get('isNew')
|
||||
@set('model', null)
|
||||
@set('isEditing', false)
|
||||
|
||||
edit: ->
|
||||
@set('isEditing', true)
|
|
@ -8,101 +8,6 @@ Ember.Handlebars.helper('mb', (size) ->
|
|||
(size / 1024 / 1024).toFixed(2)
|
||||
, 'size')
|
||||
|
||||
Travis.Tab = Ember.Object.extend
|
||||
show: ->
|
||||
@get('tabs').forEach( (t) -> t.hide() )
|
||||
@set('visible', true)
|
||||
|
||||
hide: ->
|
||||
@set('visible', false)
|
||||
|
||||
Travis.TabsView = Ember.View.extend
|
||||
tabBinding: 'controller.tab'
|
||||
tabsBinding: 'controller.tabs'
|
||||
|
||||
tabDidChange: (->
|
||||
@activateTab(@get('tab'))
|
||||
).observes('tab')
|
||||
|
||||
tabsDidChange: (->
|
||||
tab = @get('tab')
|
||||
if tab
|
||||
@activateTab(tab)
|
||||
else if @get('tabs.length')
|
||||
@activateTab(@get('tabs.firstObject.id'))
|
||||
).observes('tabs.length', 'tabs')
|
||||
|
||||
activateTab: (tabId) ->
|
||||
tab = @get('tabs').findBy('id', tabId)
|
||||
|
||||
return unless tab
|
||||
|
||||
tab.show() unless tab.get('visible')
|
||||
|
||||
# TODO: remove hardcoded link
|
||||
layout: Ember.Handlebars.compile(
|
||||
'<ul class="tabs">' +
|
||||
' {{#each tab in tabs}}' +
|
||||
' <li {{bindAttr class="tab.visible:active"}}>' +
|
||||
' <h5>{{#link-to "repo.settings.tab" tab.id}}{{tab.name}}{{/link-to}}</h5>' +
|
||||
' </li>' +
|
||||
' {{/each}}' +
|
||||
'</ul>' +
|
||||
'{{yield}}')
|
||||
|
||||
Travis.TabView = Ember.View.extend
|
||||
attributeBindings: ['style']
|
||||
|
||||
style: (->
|
||||
if !@get('tab.visible')
|
||||
'display: none'
|
||||
).property('tab.visible')
|
||||
|
||||
Ember.Handlebars.registerHelper('travis-tab', (id, name, options) ->
|
||||
controller = this
|
||||
controller.set('tabs', []) unless controller.get('tabs')
|
||||
|
||||
tab = Travis.Tab.create(id: id, name: name, tabs: controller.get('tabs'))
|
||||
|
||||
view = Travis.TabView.create(
|
||||
controller: this
|
||||
tab: tab
|
||||
)
|
||||
|
||||
controller = this
|
||||
Ember.run.schedule('afterRender', ->
|
||||
if controller.get('tabs.length') == 0
|
||||
tab.show()
|
||||
controller.get('tabs').pushObject(tab)
|
||||
)
|
||||
|
||||
Ember.Handlebars.helpers.view.call(this, view, options)
|
||||
)
|
||||
|
||||
|
||||
Ember.Handlebars.registerHelper('travis-tabs', (options) ->
|
||||
template = options.fn
|
||||
delete options.fn
|
||||
|
||||
@set('tabs', [])
|
||||
|
||||
view = Travis.TabsView.create(
|
||||
controller: this
|
||||
template: template
|
||||
)
|
||||
|
||||
Ember.Handlebars.helpers.view.call(this, view, options)
|
||||
)
|
||||
|
||||
Travis.FormSettingsView = Ember.View.extend Ember.TargetActionSupport,
|
||||
target: Ember.computed.alias('controller')
|
||||
actionContext: Ember.computed.alias('context'),
|
||||
action: 'submit'
|
||||
tagName: 'form'
|
||||
submit: (event) ->
|
||||
event.preventDefault()
|
||||
@triggerAction()
|
||||
|
||||
Ember.LinkView.reopen
|
||||
init: ->
|
||||
@_super()
|
||||
|
@ -114,18 +19,100 @@ Ember.LinkView.reopen
|
|||
_trackEvent: (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
Ember.Handlebars.registerHelper('settings-form', (path, options) ->
|
||||
if arguments.length == 1
|
||||
options = path
|
||||
path = 'settings'
|
||||
FormFieldRowView = Ember.View.extend
|
||||
invalid: Ember.computed.notEmpty('errors.[]')
|
||||
classNameBindings: ['invalid']
|
||||
classNames: 'field'
|
||||
|
||||
view = Travis.FormSettingsView.create(
|
||||
template: options.fn
|
||||
LabelView = Ember.View.extend(
|
||||
tagName: 'label'
|
||||
|
||||
attributeBindings: ['for', 'accesskey', 'form']
|
||||
classNameBindings: ['class']
|
||||
)
|
||||
|
||||
Ember.Handlebars.registerHelper('label', (options) ->
|
||||
view = LabelView
|
||||
|
||||
name = options.hash.for
|
||||
if name
|
||||
labels = @get('_labels')
|
||||
unless labels
|
||||
labels = Ember.Object.create()
|
||||
@set('_labels', labels)
|
||||
|
||||
# for now I support only label + input in their own context
|
||||
id = labels.get(name)
|
||||
unless id
|
||||
id = "#{name}-#{Math.round(Math.random() * 1000000)}"
|
||||
labels.set(name, id)
|
||||
|
||||
options.hash.for = id
|
||||
options.hashTypes.for = 'STRING'
|
||||
options.hashContexts.for = this
|
||||
|
||||
Ember.Handlebars.helpers.view.call(this, view, options)
|
||||
)
|
||||
|
||||
originalInputHelper = Ember.Handlebars.helpers.input
|
||||
|
||||
Ember.Handlebars.registerHelper('input', (options) ->
|
||||
# for now I can match label only with the property name
|
||||
# passed here matches the label
|
||||
name = (options.hash.value || options.hash.checked)
|
||||
id = options.hash.id
|
||||
|
||||
# generate id only if it's not given
|
||||
if name && !name.match(/\./) && !id
|
||||
labels = @get('_labels')
|
||||
unless labels
|
||||
labels = Ember.Object.create()
|
||||
@set('_labels', labels)
|
||||
|
||||
# for now I support only label + input in their own context
|
||||
id = labels.get(name)
|
||||
unless id
|
||||
id = "#{name}-#{Math.round(Math.random() * 1000000)}"
|
||||
labels.set(name, id)
|
||||
|
||||
options.hash.id = id
|
||||
options.hashTypes.id = 'STRING'
|
||||
options.hashContexts.id = this
|
||||
|
||||
originalInputHelper.call(this, options)
|
||||
)
|
||||
|
||||
Ember.Handlebars.registerHelper('travis-field', (name, options) ->
|
||||
errors = @get('errors').for(name)
|
||||
template = options.fn
|
||||
delete options.fn
|
||||
|
||||
view = FormFieldRowView.create(
|
||||
controller: this
|
||||
settingsPath: path
|
||||
template: template
|
||||
errors: errors
|
||||
name: name
|
||||
classNameBindings: ['name']
|
||||
)
|
||||
|
||||
delete options.fn
|
||||
Ember.Handlebars.helpers.view.call(this, view, options)
|
||||
)
|
||||
|
||||
Travis.ErrorsView = Ember.View.extend
|
||||
tagName: 'span'
|
||||
template: Ember.Handlebars.compile("{{#each view.errors}}{{message}}{{/each}}")
|
||||
classNames: ['error']
|
||||
classNameBindings: ['codes']
|
||||
codes: (->
|
||||
@get('errors').mapBy('code')
|
||||
).property('@errors')
|
||||
|
||||
Ember.Handlebars.helper('travis-errors', (name, options) ->
|
||||
errors = @get('errors').for(name)
|
||||
view = Travis.ErrorsView.create(
|
||||
controller: this
|
||||
errors: errors
|
||||
)
|
||||
|
||||
Ember.Handlebars.helpers.view.call(this, view, options)
|
||||
)
|
||||
|
|
|
@ -13,4 +13,5 @@ require 'models/repo'
|
|||
require 'models/request'
|
||||
require 'models/user'
|
||||
require 'models/worker'
|
||||
|
||||
require 'models/env_var'
|
||||
require 'models/ssh_key'
|
||||
|
|
16
assets/scripts/app/models/env_var.coffee
Normal file
16
assets/scripts/app/models/env_var.coffee
Normal file
|
@ -0,0 +1,16 @@
|
|||
require 'travis/model'
|
||||
|
||||
Travis.EnvVar = Travis.Model.extend
|
||||
name: Ember.attr('string')
|
||||
value: Ember.attr('string')
|
||||
public: Ember.attr('boolean')
|
||||
|
||||
repo: Ember.belongsTo('Travis.Repo', key: 'repository_id')
|
||||
|
||||
isPropertyLoaded: (key) ->
|
||||
if key == 'value'
|
||||
return true
|
||||
else
|
||||
@_super(key)
|
||||
|
||||
|
|
@ -23,6 +23,29 @@ require 'travis/model'
|
|||
}
|
||||
).property('lastBuildId', 'lastBuildNumber')
|
||||
|
||||
sshKey: (->
|
||||
Travis.SshKey.find(@get('id'))
|
||||
)
|
||||
|
||||
envVars: (->
|
||||
id = @get('id')
|
||||
envVars = Travis.EnvVar.find repository_id: id
|
||||
|
||||
# TODO: move to controller
|
||||
array = Travis.ExpandableRecordArray.create
|
||||
type: Travis.EnvVar
|
||||
content: Ember.A([])
|
||||
|
||||
array.load(envVars)
|
||||
|
||||
globalEnvVars = Ember.RecordArray.create({ modelClass: Travis.EnvVar, content: Ember.A([]) })
|
||||
Travis.EnvVar.registerRecordArray(globalEnvVars)
|
||||
|
||||
array.observe(globalEnvVars, (envVar) -> envVar.get('isLoaded') && envVar.get('repo.id') == id )
|
||||
|
||||
array
|
||||
).property()
|
||||
|
||||
allBuilds: (->
|
||||
recordArray = Ember.RecordArray.create({ modelClass: Travis.Build, content: Ember.A([]) })
|
||||
Travis.Build.registerRecordArray(recordArray)
|
||||
|
|
13
assets/scripts/app/models/ssh_key.coffee
Normal file
13
assets/scripts/app/models/ssh_key.coffee
Normal file
|
@ -0,0 +1,13 @@
|
|||
Travis.SshKey = Travis.Model.extend
|
||||
id: Ember.attr('string')
|
||||
value: Ember.attr('string')
|
||||
description: Ember.attr('string')
|
||||
fingerprint: Ember.attr('string')
|
||||
|
||||
isPropertyLoaded: (key) ->
|
||||
if key == 'value'
|
||||
return true
|
||||
else
|
||||
@_super(key)
|
||||
|
||||
|
|
@ -62,10 +62,11 @@ Travis.Router.map ->
|
|||
@resource 'caches', path: '/caches' if Travis.config.caches_enabled
|
||||
@resource 'request', path: '/requests/:request_id'
|
||||
|
||||
# this can't be nested in repo, because we want a set of different
|
||||
# templates rendered for settings (for example no "current", "builds", ... tabs)
|
||||
@resource 'repo.settings', path: '/:owner/:name/settings', ->
|
||||
@route 'tab', path: ':tab'
|
||||
@resource 'settings', ->
|
||||
@route 'index', path: '/'
|
||||
@resource 'env_vars', ->
|
||||
@route 'new'
|
||||
@resource 'ssh_key' if Travis.config.ssh_key_enabled
|
||||
|
||||
@route 'first_sync'
|
||||
@route 'insufficient_oauth_permissions'
|
||||
|
@ -380,24 +381,40 @@ Travis.AuthRoute = Travis.Route.extend
|
|||
@transitionTo('index.current')
|
||||
return true
|
||||
|
||||
Travis.RepoSettingsRoute = Travis.Route.extend
|
||||
Travis.SettingsRoute = Travis.Route.extend
|
||||
setupController: (controller, model) ->
|
||||
# TODO: if repo is just a data hash with id and slug load it
|
||||
# as incomplete record
|
||||
model = Travis.Repo.find(model.id) if model && !model.get
|
||||
@_super(controller, model)
|
||||
@controllerFor('repo').activate('settings')
|
||||
|
||||
serialize: (repo) ->
|
||||
slug = if repo.get then repo.get('slug') else repo.slug
|
||||
[owner, name] = slug.split('/')
|
||||
{ owner: owner, name: name }
|
||||
|
||||
model: (params) ->
|
||||
slug = "#{params.owner}/#{params.name}"
|
||||
Travis.Repo.fetchBySlug(slug)
|
||||
|
||||
afterModel: (repo) ->
|
||||
# I'm using afterModel to fetch settings, because model is not always called.
|
||||
# If link-to already provides a model, it will be just set as a route context.
|
||||
Travis.SettingsIndexRoute = Travis.Route.extend
|
||||
model: ->
|
||||
repo = @modelFor('repo')
|
||||
repo.fetchSettings().then (settings) ->
|
||||
repo.set('settings', settings)
|
||||
|
||||
Travis.EnvVarsRoute = Travis.Route.extend
|
||||
model: (params) ->
|
||||
repo = @modelFor('repo')
|
||||
repo.get('envVars.promise')
|
||||
|
||||
Travis.SshKeyRoute = Travis.Route.extend
|
||||
model: (params) ->
|
||||
repo = @modelFor('repo')
|
||||
self = this
|
||||
Travis.SshKey.fetch(repo.get('id')).then ( (result) -> result ), (xhr) ->
|
||||
if xhr.status == 404
|
||||
# if there is no model, just return null. I'm not sure if this is the
|
||||
# best answer, maybe we should just redirect to different route, like
|
||||
# ssh_key.new or ssh_key.no_key
|
||||
return null
|
||||
|
||||
afterModel: (model, transition) ->
|
||||
repo = @modelFor('repo')
|
||||
Travis.ajax.get "/repositories/#{repo.get('id')}/key", (data) =>
|
||||
@defaultKey = Ember.Object.create(fingerprint: data.fingerprint)
|
||||
|
||||
setupController: (controller, model) ->
|
||||
@_super.apply this, arguments
|
||||
|
||||
if @defaultKey
|
||||
controller.set('defaultKey', @defaultKey)
|
||||
@defaultKey = null
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
<p class="description">{{hook.description}}</p>
|
||||
|
||||
<div class="controls">
|
||||
{{#link-to "repo.settings" hook.repo class="repo-settings-icon tool-tip" title="Repository settings"}}{{/link-to}}
|
||||
{{#link-to "settings" hook.repo class="repo-settings-icon tool-tip" title="Repository settings"}}{{/link-to}}
|
||||
{{travis-switch action="toggle" target=hook toggleAutomatically="false"}}
|
||||
</div>
|
||||
</li>
|
||||
|
|
18
assets/scripts/app/templates/env_vars.hbs
Normal file
18
assets/scripts/app/templates/env_vars.hbs
Normal file
|
@ -0,0 +1,18 @@
|
|||
{{outlet}}
|
||||
|
||||
<ul class="env-vars">
|
||||
{{#each controller itemController="envVar"}}
|
||||
<li class="env-var">
|
||||
{{#if isEditing}}
|
||||
{{partial 'env_vars/form'}}
|
||||
{{else}}
|
||||
<a href="#" class="edit-var" {{action "edit"}}>Edit</a>
|
||||
<a href="#" {{action "delete"}} {{bind-attr class=":delete-var isDeleting:deleting"}}>
|
||||
Delete
|
||||
</a>
|
||||
<span class="name">{{name}}</span>
|
||||
<span {{bind-attr class=":value :value-display public::secure"}}>{{value}}</span>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
26
assets/scripts/app/templates/env_vars/_form.hbs
Normal file
26
assets/scripts/app/templates/env_vars/_form.hbs
Normal file
|
@ -0,0 +1,26 @@
|
|||
<form class="env-var" {{action "save" on="submit"}}>
|
||||
{{#travis-field "name"}}
|
||||
{{#label for="name" class="name"}}Name:{{/label}}
|
||||
{{input value=name class="env-name" placeholder="Name"}} {{travis-errors "name"}}
|
||||
{{/travis-field}}
|
||||
<span class="equals">=</span>
|
||||
{{#if showValueField}}
|
||||
<div class="field value">
|
||||
{{#label for="value" class="value"}}Value:{{/label}}
|
||||
{{input value=value class="env-value" placeholder="Value"}}
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="value value-display secure">{{value}}</span>
|
||||
{{/if}}
|
||||
<div style="clear: both"></div>
|
||||
<div class="field">
|
||||
{{travis-switch active=public class="value"}}
|
||||
{{#label for="secure" class="public"}}Display value in build logs{{/label}}
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<input type="submit" {{bind-attr value=actionType class=":submit-env-var isSaving:saving" disabled=isSaving}} />
|
||||
<span class="or">or</span>
|
||||
<a href="#" class="cancel-env-var" {{action "cancel"}}>Cancel</a>
|
||||
</div>
|
||||
</form>
|
1
assets/scripts/app/templates/env_vars/index.hbs
Normal file
1
assets/scripts/app/templates/env_vars/index.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{#link-to "env_vars.new" class="add-env-var"}}Add a new variable{{/link-to}}
|
1
assets/scripts/app/templates/env_vars/new.hbs
Normal file
1
assets/scripts/app/templates/env_vars/new.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
{{partial 'env_vars/form'}}
|
|
@ -57,6 +57,15 @@
|
|||
{{/if}}
|
||||
</h5>
|
||||
</li>
|
||||
<li id="tab_settings" {{bind-attr class="view.classSettings"}}>
|
||||
<h5>
|
||||
{{#if repo.slug}}
|
||||
{{#link-to "settings" repo}}
|
||||
Settings
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
</h5>
|
||||
</li>
|
||||
<li id="tab_requests" {{bind-attr class="view.classRequests"}}>
|
||||
<h5>
|
||||
{{#if repo.slug}}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{{/if}}
|
||||
{{#if view.displaySettingsLink}}
|
||||
<li>
|
||||
{{#link-to "repo.settings" view.repo}}Settings{{/link-to}}
|
||||
{{#link-to "settings" view.repo}}Settings{{/link-to}}
|
||||
</li>
|
||||
{{/if}}
|
||||
<li>
|
||||
|
|
11
assets/scripts/app/templates/settings.hbs
Normal file
11
assets/scripts/app/templates/settings.hbs
Normal file
|
@ -0,0 +1,11 @@
|
|||
<ul class="navigation">
|
||||
<li>{{#link-to "settings.index"}}General Settings{{/link-to}}</li>
|
||||
<li>{{#link-to "env_vars"}}Environment Variables{{/link-to}}</li>
|
||||
{{#if Travis.config.ssh_key_enabled}}
|
||||
<li>{{#link-to "ssh_key"}}SSH Key{{/link-to}}</li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
|
||||
<div id="settings">
|
||||
{{outlet}}
|
||||
</div>
|
25
assets/scripts/app/templates/settings/index.hbs
Normal file
25
assets/scripts/app/templates/settings/index.hbs
Normal file
|
@ -0,0 +1,25 @@
|
|||
<form class='settings-form'>
|
||||
<p class="settings-row">
|
||||
Build only if .travis.yml is present
|
||||
{{travis-switch action="save" active=settings.builds_only_with_travis_yml}}
|
||||
</p>
|
||||
|
||||
<p class="settings-row">
|
||||
Build pushes
|
||||
{{travis-switch action="save" active=settings.build_pushes}}
|
||||
</p>
|
||||
|
||||
<p class="settings-row">
|
||||
Build pull requests
|
||||
{{travis-switch action="save" active=settings.build_pull_requests}}
|
||||
</p>
|
||||
|
||||
<p class="settings-row">
|
||||
<p class="short-settings-element" {{bind-attr class="settings.maximum_number_of_builds_valid"}}>
|
||||
{{input value=settings.maximum_number_of_builds size="4" pattern='/^[0-9]+$/'}}
|
||||
</p>
|
||||
<label>
|
||||
Concurrent builds
|
||||
</label>
|
||||
</p>
|
||||
</form>
|
1
assets/scripts/app/templates/settings/loading.hbs
Normal file
1
assets/scripts/app/templates/settings/loading.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
<div class="loading"><span>Loading</span></div>
|
30
assets/scripts/app/templates/ssh_key.hbs
Normal file
30
assets/scripts/app/templates/ssh_key.hbs
Normal file
|
@ -0,0 +1,30 @@
|
|||
{{#if model}}
|
||||
{{#if isEditing}}
|
||||
{{partial "ssh_key/form"}}
|
||||
{{else}}
|
||||
<div class="ssh-key">
|
||||
<p>SSH key is set.</p>
|
||||
{{#if description}}
|
||||
<div class="row">
|
||||
<span class="label">Description:</label>
|
||||
<span class="value">{{description}}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="row">
|
||||
<span class="label">Fingerprint:</label>
|
||||
<span class="value">{{fingerprint}}</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<a href="#" {{action "delete"}} {{bind-attr class=":delete-ssh-key isDeleting:deleting"}}>
|
||||
Delete
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<p>
|
||||
You don't have any custom key set up.
|
||||
The default key's fingerprint is <code>{{defaultKey.fingerprint}}</code>
|
||||
</p>
|
||||
|
||||
<a {{action "add"}} href="#" class="add-ssh-key">Add a custom SSH key</a>
|
||||
{{/if}}
|
16
assets/scripts/app/templates/ssh_key/_form.hbs
Normal file
16
assets/scripts/app/templates/ssh_key/_form.hbs
Normal file
|
@ -0,0 +1,16 @@
|
|||
<form class="ssh-key" {{action "save" on="submit"}}>
|
||||
<div class="field">
|
||||
<label>Description:</label>
|
||||
{{input value=description}}
|
||||
</div>
|
||||
{{#travis-field "value"}}
|
||||
<label class="value">Private Key:</label>
|
||||
{{textarea value=value}} {{travis-errors "value"}}
|
||||
{{/travis-field}}
|
||||
|
||||
<div class="actions">
|
||||
<input type="submit" {{bind-attr value=actionType class=":submit-ssh-key isSaving:saving" disabled=isSaving}} />
|
||||
<span class="or">or</span>
|
||||
<a href="#" class="cancel-ssh-key" {{action "cancel"}}>Cancel</a>
|
||||
</div>
|
||||
</form>
|
|
@ -79,6 +79,10 @@ Travis.reopen
|
|||
'active display-inline' if @get('tab') == 'caches'
|
||||
).property('tab')
|
||||
|
||||
classSettings: (->
|
||||
'active display-inline' if @get('tab') == 'settings'
|
||||
).property('tab')
|
||||
|
||||
classRequest: (->
|
||||
'active display-inline' if @get('tab') == 'request'
|
||||
).property('tab')
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
get = Ember.get
|
||||
|
||||
Travis.Adapter = Ember.RESTAdapter.extend
|
||||
ajax: (url, params, method) ->
|
||||
Travis.ajax.ajax(url, method || 'get', data: params)
|
||||
|
@ -17,7 +19,7 @@ Travis.Adapter = Ember.RESTAdapter.extend
|
|||
records.load(klass, dataToLoad)
|
||||
@addToRecordArrays(records.get('content'))
|
||||
|
||||
buildURL: ->
|
||||
buildURL: (klass, id, record) ->
|
||||
@_super.apply(this, arguments).replace(/\.json$/, '')
|
||||
|
||||
didFind: (record, id, data) ->
|
||||
|
@ -55,7 +57,6 @@ Travis.Adapter = Ember.RESTAdapter.extend
|
|||
for record in records
|
||||
record.constructor.addToRecordArrays(record)
|
||||
|
||||
|
||||
sideload: (klass, data) ->
|
||||
for name, records of data
|
||||
records = [records] unless Ember.isArray(records)
|
||||
|
@ -66,4 +67,35 @@ Travis.Adapter = Ember.RESTAdapter.extend
|
|||
record = type.findFromCacheOrLoad(record)
|
||||
@addToRecordArrays(record)
|
||||
|
||||
find: (record, id) ->
|
||||
url = @buildURL(record.constructor, id, record)
|
||||
self = this
|
||||
@ajax(url).then (data) ->
|
||||
self.didFind record, id, data
|
||||
record
|
||||
|
||||
createRecord: (record) ->
|
||||
url = @buildURL(record.constructor, undefined, record)
|
||||
self = this
|
||||
@ajax(url, record.toJSON(), "POST").then (data) ->
|
||||
self.didCreateRecord record, data
|
||||
record
|
||||
|
||||
deleteRecord: (record) ->
|
||||
primaryKey = get(record.constructor, "primaryKey")
|
||||
url = @buildURL(record.constructor, get(record, primaryKey), record)
|
||||
self = this
|
||||
@ajax(url, record.toJSON(), "DELETE").then (data) -> # TODO: Some APIs may or may not return data
|
||||
self.didDeleteRecord record, data
|
||||
return
|
||||
|
||||
saveRecord: (record) ->
|
||||
primaryKey = get(record.constructor, 'primaryKey')
|
||||
url = this.buildURL(record.constructor, get(record, primaryKey), record)
|
||||
self = this
|
||||
|
||||
return this.ajax(url, record.toJSON(), "PATCH").then (data) ->
|
||||
self.didSaveRecord(record, data)
|
||||
return record
|
||||
|
||||
|
||||
|
|
10
assets/scripts/lib/travis/adapters/env_vars.coffee
Normal file
10
assets/scripts/lib/travis/adapters/env_vars.coffee
Normal file
|
@ -0,0 +1,10 @@
|
|||
require 'travis/adapter'
|
||||
get = Ember.get
|
||||
|
||||
Travis.EnvVarsAdapter = Travis.Adapter.extend
|
||||
buildURL: (klass, id, record) ->
|
||||
url = @_super.apply this, arguments
|
||||
if record && (repo_id = get(record, 'repository_id') || get(record, 'repo.id'))
|
||||
url = "#{url}?repository_id=#{repo_id}"
|
||||
|
||||
url
|
10
assets/scripts/lib/travis/adapters/ssh_key.coffee
Normal file
10
assets/scripts/lib/travis/adapters/ssh_key.coffee
Normal file
|
@ -0,0 +1,10 @@
|
|||
Travis.SshKeyAdapter = Travis.Adapter.extend
|
||||
buildURL: (klass, id, record) ->
|
||||
url = @_super.apply this, arguments
|
||||
|
||||
createRecord: (record) ->
|
||||
url = @buildURL(record.constructor, record.get('id'), record)
|
||||
self = this
|
||||
@ajax(url, record.toJSON(), "PATCH").then (data) ->
|
||||
self.didCreateRecord record, data
|
||||
record
|
|
@ -2,6 +2,23 @@ Travis.ExpandableRecordArray = Ember.RecordArray.extend
|
|||
isLoaded: false
|
||||
isLoading: false
|
||||
|
||||
promise: (->
|
||||
console.log 'promise'
|
||||
self = this
|
||||
new Ember.RSVP.Promise (resolve, reject) ->
|
||||
console.log 'inside promise'
|
||||
observer = ->
|
||||
console.log 'observer', self.get('isLoaded')
|
||||
if self.get('isLoaded')
|
||||
console.log 'resolve'
|
||||
resolve(self)
|
||||
self.removeObserver('isLoaded', observer)
|
||||
true
|
||||
|
||||
unless observer()
|
||||
self.addObserver 'isLoaded', observer
|
||||
).property()
|
||||
|
||||
load: (array) ->
|
||||
@set 'isLoading', true
|
||||
self = this
|
||||
|
@ -25,11 +42,17 @@ Travis.ExpandableRecordArray = Ember.RecordArray.extend
|
|||
willChange: 'observedArrayWillChange'
|
||||
didChange: 'observedArraydidChange'
|
||||
|
||||
observedArrayWillChange: (->)
|
||||
observedArrayWillChange: (array, index, removedCount, addedCount) ->
|
||||
removedObjects = array.slice index, index + removedCount
|
||||
for object in removedObjects
|
||||
@removeObject(object)
|
||||
|
||||
observedArraydidChange: (array, index, removedCount, addedCount) ->
|
||||
addedObjects = array.slice index, index + addedCount
|
||||
for object in addedObjects
|
||||
if @get('filterWith').call this, object
|
||||
# TODO: I'm not sure why deleted objects get here, but I'll just filter them
|
||||
# for now
|
||||
if !object.get('isDeleted') && @get('filterWith').call(this, object)
|
||||
@pushObject(object) unless @contains(object)
|
||||
|
||||
pushObject: (record) ->
|
||||
|
|
87
assets/scripts/lib/travis/validations.coffee
Normal file
87
assets/scripts/lib/travis/validations.coffee
Normal file
|
@ -0,0 +1,87 @@
|
|||
get = Ember.get
|
||||
|
||||
Error = Ember.Object.extend
|
||||
message: (->
|
||||
switch @get('code')
|
||||
when 'blank' then "can't be blank"
|
||||
when 'not_a_private_key' then "the key is not a valid private key"
|
||||
else "unknown error"
|
||||
).property('code')
|
||||
|
||||
FieldErrors = Ember.ArrayProxy.extend
|
||||
add: (error) ->
|
||||
@get('content').pushObject(error)
|
||||
|
||||
isValid: ->
|
||||
@get('length') == 0
|
||||
|
||||
Errors = Ember.ArrayProxy.extend
|
||||
for: (name) ->
|
||||
fieldErrors = @findBy('name', name)
|
||||
unless fieldErrors
|
||||
fieldErrors = FieldErrors.create(name: name, content: [])
|
||||
@get('content').pushObject(fieldErrors)
|
||||
|
||||
fieldErrors
|
||||
|
||||
add: (name, code) ->
|
||||
@for(name).add(Error.create(name: name, code: code))
|
||||
|
||||
isValid: ->
|
||||
@every (fieldErrors) -> fieldErrors.isValid()
|
||||
|
||||
clear: ->
|
||||
@forEach (fieldErrors) -> fieldErrors.clear()
|
||||
|
||||
Validator = Ember.Object.extend
|
||||
setError: (target) ->
|
||||
target.get('errors').add(@get('name'), @get('code'))
|
||||
|
||||
isValid: (target) ->
|
||||
name = @get('name')
|
||||
@get('validator').call(target, get(target, name))
|
||||
|
||||
validate: (target) ->
|
||||
unless @isValid(target)
|
||||
@setError(target)
|
||||
|
||||
Travis.Validations = Ember.Mixin.create
|
||||
init: ->
|
||||
@_super.apply this, arguments
|
||||
|
||||
@validators = []
|
||||
@set('errors', Errors.create(content: []))
|
||||
|
||||
if validations = @get('validates')
|
||||
for field, properties of validations
|
||||
for property in properties
|
||||
@_addValidation(field, property)
|
||||
|
||||
_addValidation: (name, type) ->
|
||||
observer = ->
|
||||
@get('errors').for(name).clear()
|
||||
@addObserver(name, this, observer)
|
||||
@["_add#{type.capitalize()}Validator"].call(this, name)
|
||||
|
||||
_addPresenceValidator: (name) ->
|
||||
@_addValidator name, "blank", (value) ->
|
||||
!Ember.isBlank(value)
|
||||
|
||||
_addValidator: (name, code, validator) ->
|
||||
@validators.pushObject(Validator.create(name: name, code: code, validator: validator))
|
||||
|
||||
validate: ->
|
||||
@get('errors').clear()
|
||||
for validator in @validators
|
||||
validator.validate(this)
|
||||
|
||||
isValid: ->
|
||||
@validate()
|
||||
@get('errors').isValid()
|
||||
|
||||
clearValidations: ->
|
||||
@get('errors').clear()
|
||||
|
||||
addErrorsFromResponse: (errors) ->
|
||||
for error in errors
|
||||
@get('errors').add(error.field, error.code)
|
|
@ -81,6 +81,7 @@ $.extend Travis,
|
|||
pusher_key: $('meta[name="travis.pusher_key"]').attr('value')
|
||||
ga_code: $('meta[name="travis.ga_code"]').attr('value')
|
||||
code_climate: $('meta[name="travis.code_climate"]').attr('value')
|
||||
ssh_key_enabled: $('meta[name="travis.ssh_key_enabled"]').attr('value') == 'true'
|
||||
code_climate_url: $('meta[name="travis.code_climate_url"]').attr('value')
|
||||
caches_enabled: $('meta[name="travis.caches_enabled"]').attr('value') == 'true'
|
||||
show_repos_hint: 'private'
|
||||
|
@ -163,6 +164,8 @@ Ember.LinkView.reopen
|
|||
|
||||
require 'travis/ajax'
|
||||
require 'travis/adapter'
|
||||
require 'travis/adapters/env_vars'
|
||||
require 'travis/adapters/ssh_key'
|
||||
require 'routes'
|
||||
require 'auth'
|
||||
require 'controllers'
|
||||
|
|
|
@ -11,15 +11,15 @@ p.settings-row
|
|||
position: relative
|
||||
display: inline-block
|
||||
float: left
|
||||
width: 60px
|
||||
height: 18px
|
||||
width: 5em
|
||||
height: 1.55em
|
||||
margin: 20px 0 50px 0
|
||||
padding: 5px 18px 5px 18px
|
||||
padding: 0.42em 1.5em
|
||||
background-color: #F5F5F5
|
||||
border: 1px solid #E3E1E1
|
||||
border-radius: 4px
|
||||
line-height: 19px
|
||||
font-size: 11px
|
||||
line-height: 1.58em
|
||||
font-size: 12px
|
||||
color: #999999
|
||||
cursor: pointer
|
||||
text-align: right
|
||||
|
@ -28,15 +28,13 @@ p.settings-row
|
|||
position: absolute
|
||||
top: 1px
|
||||
left: 1px
|
||||
width: 42px
|
||||
height: 24px
|
||||
width: 3.5em
|
||||
height: 1.9em
|
||||
background: #e9e9e7
|
||||
border: 1px solid #d7d4d4
|
||||
border-radius: 2px
|
||||
|
||||
.travis-switch.active
|
||||
width: 60px
|
||||
padding: 5px 18px 5px 18px
|
||||
background-color: #607A83
|
||||
border-radius: 4px
|
||||
color: #ffffff
|
||||
|
@ -45,8 +43,6 @@ p.settings-row
|
|||
&:before
|
||||
left: auto
|
||||
right: 1px
|
||||
width: 42px
|
||||
height: 24px
|
||||
border: 1px solid #9cafb5
|
||||
|
||||
span.on
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
margin-top: 5px
|
||||
|
||||
#hooks, #unadministerable-hooks
|
||||
.travis-switch
|
||||
font-size: 10px
|
||||
// @include list-base
|
||||
margin-top: 10px
|
||||
|
||||
|
|
|
@ -1,33 +1,281 @@
|
|||
form
|
||||
margin: 20px
|
||||
#settings
|
||||
.settings-form
|
||||
margin: 30px 0 30px 0
|
||||
|
||||
p.short-settings-element
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
margin: 0 10px 0 0
|
||||
float: left
|
||||
p.short-settings-element
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
margin: 0 10px 0 0
|
||||
float: left
|
||||
|
||||
label
|
||||
line-height: 30px
|
||||
label
|
||||
line-height: 30px
|
||||
|
||||
input
|
||||
display: inline-block
|
||||
float: left
|
||||
width: 60px
|
||||
height: 18px
|
||||
padding: 5px 18px 5px 18px
|
||||
background-color: #F5F5F5
|
||||
border: 1px solid #E3E1E1
|
||||
border-radius: 4px
|
||||
line-height: 19px
|
||||
font-size: 11px
|
||||
color: #999999
|
||||
text-align: center
|
||||
|
||||
.invalid
|
||||
input
|
||||
display: inline-block
|
||||
float: left
|
||||
width: 60px
|
||||
height: 18px
|
||||
padding: 5px 18px 5px 18px
|
||||
background-color: #F5F5F5
|
||||
border: 1px solid #E3E1E1
|
||||
border-radius: 4px
|
||||
line-height: 19px
|
||||
font-size: 11px
|
||||
color: #999999
|
||||
text-align: center
|
||||
|
||||
.field.invalid
|
||||
input, textarea
|
||||
border-width: 1px
|
||||
border-color: #ffb6c1
|
||||
background: rgb(252, 227, 230)
|
||||
|
||||
form.env-var, form.ssh-key
|
||||
margin-top: 20px
|
||||
|
||||
.field
|
||||
padding-bottom: 10px
|
||||
.field:after
|
||||
visibility: hidden
|
||||
display: block
|
||||
font-size: 0
|
||||
content: " "
|
||||
clear: both
|
||||
height: 0
|
||||
|
||||
label
|
||||
display: inline-block
|
||||
|
||||
form.env-var
|
||||
label
|
||||
width: 40px
|
||||
label.value
|
||||
width: auto
|
||||
line-height: 1.9em
|
||||
.travis-switch.value
|
||||
font-size: 10px
|
||||
form.ssh-key
|
||||
span.error
|
||||
display: block
|
||||
margin-left: 76px
|
||||
label
|
||||
width: 73px
|
||||
label.value
|
||||
float: left
|
||||
textarea
|
||||
margin-left: 3px
|
||||
width: 580px
|
||||
height: 250px
|
||||
display: inline-block
|
||||
padding: 0 5px 0 5px
|
||||
background-color: #fff
|
||||
border: 1px solid #ddd
|
||||
line-height: 17px
|
||||
font-size: 13px
|
||||
color: #999999
|
||||
text-align: left
|
||||
|
||||
span.error
|
||||
display: inline-block
|
||||
margin-left: 10px
|
||||
color: #a80000
|
||||
|
||||
.env-var input[type=submit].saving, .ssh-key input[type=submit].saving,
|
||||
.env-var .delete-var.deleting, .delete-ssh-key.deleting
|
||||
background-color: #bbb
|
||||
background-image: inline-image('ui/round-spinner.svg')
|
||||
background-repeat: no-repeat
|
||||
background-position: center
|
||||
background-size: 20px
|
||||
text-indent: -9999px
|
||||
|
||||
.env-var-name
|
||||
span
|
||||
font-size: 18px
|
||||
font-weight: 600
|
||||
color: #5e6872
|
||||
|
||||
span.value.value-display
|
||||
font-size: 14px
|
||||
background-color: #efefdf
|
||||
border-radius: 4px
|
||||
padding: 0 10px 0 10px
|
||||
color: #838b8c
|
||||
font-family: monospace
|
||||
|
||||
span.value.value-display.secure
|
||||
background-image: inline-image('ui/secure.png')
|
||||
background-position: 8px center
|
||||
background-repeat: no-repeat
|
||||
background-size: 0.5em
|
||||
padding-left: 26px
|
||||
width: 142px
|
||||
|
||||
.add-env-var, .add-ssh-key
|
||||
color: #ffffff
|
||||
background-color: #97a3aa
|
||||
border-radius: 4px
|
||||
padding: 8px 12px 8px 12px
|
||||
margin-bottom: 20px
|
||||
font-size: 13px
|
||||
line-height: 55px
|
||||
cursor: pointer
|
||||
|
||||
.add-env-var:hover, .add-ssh-key:hover
|
||||
background-color: #7c878d
|
||||
|
||||
input
|
||||
display: inline-block
|
||||
width: 260px
|
||||
height: 20px
|
||||
padding: 0 5px 0 5px
|
||||
background-color: #fff
|
||||
border: 1px solid #ddd
|
||||
line-height: 17px
|
||||
font-size: 13px
|
||||
color: #999999
|
||||
text-align: left
|
||||
|
||||
form.env-var .actions
|
||||
margin-bottom: 35px
|
||||
|
||||
input.submit-env-var, input.submit-ssh-key
|
||||
color: #ffffff
|
||||
background-color: #7ea35a
|
||||
border-radius: 4px
|
||||
font-size: 13px
|
||||
width: 60px
|
||||
height: 32px
|
||||
text-align: center
|
||||
margin: 10px 6px 0 0
|
||||
cursor: pointer
|
||||
|
||||
.submit-env-var:hover, .submit-ssh-key:hover
|
||||
background-color: #6f924f
|
||||
|
||||
.cancel-env-var, .cancel-ssh-key
|
||||
margin-left: 3px
|
||||
|
||||
.cancel-env-var:hover, .cancel-ssh-key:hover
|
||||
text-decoration: underline
|
||||
|
||||
input[type="checkbox"]
|
||||
display: inline-block
|
||||
vertical-align: middle
|
||||
|
||||
.edit-var
|
||||
display: inline-block
|
||||
margin: 6px 10px 7px 0
|
||||
color: #ffffff
|
||||
background-color: #bcbcbb
|
||||
border-radius: 4px
|
||||
padding: 4px 15px 4px 15px
|
||||
font-size: 13px
|
||||
cursor: pointer
|
||||
|
||||
.edit-var:hover
|
||||
background-color: #a4a5a4
|
||||
|
||||
.delete-var, .delete-ssh-key
|
||||
display: inline-block
|
||||
margin: 6px 0 7px 0
|
||||
color: #ffffff
|
||||
background-color: #932828
|
||||
border-radius: 4px
|
||||
padding: 4px 15px 4px 15px
|
||||
font-size: 13px
|
||||
cursor: pointer
|
||||
|
||||
.delete-var:hover, .delete-ssh-key:hover
|
||||
background-color: #820b0b
|
||||
|
||||
form.env-var
|
||||
width: 100%
|
||||
margin-top: 20px
|
||||
margin-bottom: 30px
|
||||
border-bottom: 1px solid #f1f1f1
|
||||
label.name, label.value
|
||||
display: none
|
||||
|
||||
label.public
|
||||
width: 80%
|
||||
|
||||
.field.name, .field.value
|
||||
float: left
|
||||
padding-bottom: 0
|
||||
height: 33px
|
||||
line-height: 33px
|
||||
|
||||
span.equals
|
||||
float: left
|
||||
display: block
|
||||
line-height: 33px
|
||||
margin: 0 10px 0 14px
|
||||
|
||||
.field.name
|
||||
width: 242px
|
||||
margin-bottom: 10px
|
||||
input
|
||||
width: 97%
|
||||
.field.value
|
||||
width: 45%
|
||||
input
|
||||
width: 97%
|
||||
.actions
|
||||
margin-bottom: 10px
|
||||
|
||||
ul.env-vars
|
||||
display: block
|
||||
li.env-var
|
||||
margin: 10px 40px 0 0
|
||||
padding-bottom: 10px
|
||||
overflow: auto
|
||||
display: flex
|
||||
display: -webkit-flex
|
||||
display: -moz-flex
|
||||
-webkit-align-items: center
|
||||
-moz-align-items: center
|
||||
align-items: center
|
||||
justify-content: left
|
||||
-webkit-justify-content: left
|
||||
-moz-justify-content: left
|
||||
border-bottom: 1px solid #F1F1F1
|
||||
width: 100%
|
||||
|
||||
form.env-var
|
||||
margin-bottom: 6px
|
||||
border-bottom: none
|
||||
|
||||
.var
|
||||
font-size: 13px
|
||||
display: inline-block
|
||||
margin-right: 10px
|
||||
|
||||
.row
|
||||
.label
|
||||
display: inline-block
|
||||
border: 1px solid #ddd
|
||||
font-size: 13px
|
||||
margin-top: 4px
|
||||
height: 20px
|
||||
|
||||
span.name, span.value
|
||||
display: inline-block
|
||||
line-height: 40px
|
||||
position: relative
|
||||
font-size: 15px
|
||||
|
||||
.equals
|
||||
margin: 0 10px 0 14px
|
||||
|
||||
span.name
|
||||
width: 120px
|
||||
margin: 0 10px 0 20px
|
||||
text-align: left
|
||||
|
||||
span.value
|
||||
width: auto
|
||||
text-align: left
|
||||
min-width: 158px
|
||||
max-width: 450px
|
||||
|
|
|
@ -67,11 +67,31 @@
|
|||
.tab
|
||||
margin-top: 20px
|
||||
|
||||
ul.navigation
|
||||
margin: -18px 0 20px 0
|
||||
height: 40px
|
||||
line-height: 40px
|
||||
border-bottom: 1px solid #EAEAEA
|
||||
padding-left: 10px
|
||||
|
||||
li
|
||||
display: inline-block
|
||||
padding-right: 10px
|
||||
|
||||
a
|
||||
color: #ACACAC
|
||||
font-weight: 600
|
||||
font-size: 14px
|
||||
|
||||
a.active
|
||||
color: #55888E
|
||||
|
||||
#tab_build,
|
||||
#tab_job,
|
||||
#tab_request,
|
||||
#tab_caches,
|
||||
#tab_requests
|
||||
#tab_caches,
|
||||
#tab_settings
|
||||
display: none
|
||||
|
||||
#profile
|
||||
|
|
|
@ -33,4 +33,5 @@ run Travis::Web::App.build(
|
|||
root: File.expand_path('../public', __FILE__),
|
||||
server_start: Time.now,
|
||||
caches_enabled: ENV['CACHES_ENABLED']
|
||||
ssh_key_enabled: ENV['SSH_KEY_ENABLED']
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,800' rel='stylesheet' type='text/css'>
|
||||
<meta charset="UTF-8">
|
||||
<meta rel="travis.api_endpoint" href="https://api.travis-ci.org">
|
||||
<meta name="travis.ssh_key_enabled" value="false">
|
||||
<meta name="travis.pusher_key" value="5df8ac576dcccf4fd076">
|
||||
<meta name="travis.ga_code" value="UA-24868285-1">
|
||||
<meta name="travis.caches_enabled" value="false">
|
||||
|
|
Loading…
Reference in New Issue
Block a user