@ -1,11 +1,13 @@
< rd-header id = "view-top" >
< rd-header-title title = " Application templates list ">
< a data-toggle = "tooltip" title = " Refresh " ui-sref = "templates" ui-sref-opts = "{reload: true}" >
< rd-header-title title = " TEMPLATES.HEADER.TITLE ">
< a data-toggle = "tooltip" title = " COMMON.VERBS.REFRESH " ui-sref = "templates" ui-sref-opts = "{reload: true}" >
< i class = "fa fa-refresh" aria-hidden = "true" > < / i >
< / a >
< i id = "loadTemplatesSpinner" class = "fa fa-cog fa-spin" style = "margin-left: 5px;" > < / i >
< / rd-header-title >
< rd-header-content > Templates< / rd-header-content >
< rd-header-content >
< por-translation key = "TEMPLATES.HEADER.CONTENT" > < / por-translation >
< / rd-header-content >
< / rd-header >
< div class = "row" style = "height: 90%" >
@ -14,7 +16,9 @@
< rd-widget >
< rd-widget-custom-header icon = "state.selectedTemplate.Logo" title = "state.selectedTemplate.Image" >
< div class = "pull-right" >
< button type = "button" class = "btn btn-sm btn-primary" ng-click = "unselectTemplate()" > Hide< / button >
< button type = "button" class = "btn btn-sm btn-primary" ng-click = "unselectTemplate()" >
< por-translation key = "COMMON.VERBS.HIDE" > < / por-translation >
< / button >
< / div >
< / rd-widget-custom-header >
< rd-widget-body classes = "padding" >
@ -23,7 +27,7 @@
<!-- description -->
< div ng-if = "state.selectedTemplate.Note" >
< div class = "col-sm-12 form-section-title" >
Information
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.TITLE_INFORMATION" > < / por-translation >
< / div >
< div class = "form-group" >
< div class = "col-sm-12" >
@ -33,11 +37,13 @@
< / div >
<!-- !description -->
< div class = "col-sm-12 form-section-title" >
Configuration
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.TITLE_CONFIGURATION" > < / por-translation >
< / div >
<!-- name - input -->
< div class = "form-group" >
< label for = "container_name" class = "col-sm-2 control-label text-left" > Name< / label >
< label for = "container_name" class = "col-sm-2 control-label text-left" >
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.NAME" > < / por-translation >
< / label >
< div class = "col-sm-10" >
< input type = "text" name = "container_name" class = "form-control" ng-model = "formValues.name" placeholder = "e.g. web (optional)" >
< / div >
@ -45,10 +51,11 @@
<!-- !name - input -->
<!-- network - input -->
< div class = "form-group" >
< label for = "container_network" class = "col-sm-2 control-label text-left" > Network< / label >
< label for = "container_network" class = "col-sm-2 control-label text-left" >
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.NETWORK" > < / por-translation >
< / label >
< div class = "col-sm-10" >
< select class = "form-control" ng-options = "net.Name for net in availableNetworks" ng-model = "formValues.network" >
< option disabled hidden value = "" > Select a network< / option >
< / select >
< / div >
< / div >
@ -58,10 +65,14 @@
< label for = "field_{{ $index }}" class = "col-sm-2 control-label text-left" > {{ var.label }}< / label >
< div class = "col-sm-10" >
< select ng-if = "applicationState.endpoint.mode.provider !== 'DOCKER_SWARM' && var.type === 'container'" ng-options = "container|containername for container in runningContainers" class = "form-control" ng-model = "var.value" >
< option selected disabled hidden value = "" > Select a container< / option >
< option selected disabled hidden value = "" translate >
TEMPLATES.SELECTED_TEMPLATE.FORM.SELECT_CONTAINER
< / option >
< / select >
< select ng-if = "applicationState.endpoint.mode.provider === 'DOCKER_SWARM' && var.type === 'container'" ng-options = "container|swarmcontainername for container in runningContainers" class = "form-control" ng-model = "var.value" >
< option selected disabled hidden value = "" > Select a container< / option >
< option selected disabled hidden value = "" translate >
TEMPLATES.SELECTED_TEMPLATE.FORM.SELECT_CONTAINER
< / option >
< / select >
< input ng-if = "!var.type || !var.type === 'container'" type = "text" class = "form-control" ng-model = "var.value" id = "field_{{ $index }}" >
< / div >
@ -73,10 +84,10 @@
< div class = "form-group" >
< div class = "col-sm-12" >
< a class = "small interactive" ng-if = "!state.showAdvancedOptions" ng-click = "state.showAdvancedOptions = true;" >
< i class = "fa fa-plus space-right" aria-hidden = "true" > < / i > Show advanced options
< i class = "fa fa-plus space-right" aria-hidden = "true" > < / i > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.SHOW_ADVANCED_OPTIONS" > < / por-translation >
< / a >
< a class = "small interactive" ng-if = "state.showAdvancedOptions" ng-click = "state.showAdvancedOptions = false;" >
< i class = "fa fa-minus space-right" aria-hidden = "true" > < / i > Hide advanced options
< i class = "fa fa-minus space-right" aria-hidden = "true" > < / i > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.HIDE_ADVANCED_OPTIONS" > < / por-translation >
< / a >
< / div >
< / div >
@ -84,13 +95,15 @@
<!-- port - mapping -->
< div class = "form-group" >
< div class = "col-sm-12" style = "margin-top: 5px;" >
< label class = "control-label text-left" > Port mapping< / label >
< label class = "control-label text-left" >
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.LABEL" > < / por-translation >
< / label >
< span class = "label label-default interactive" style = "margin-left: 10px;" ng-click = "addPortBinding()" >
< i class = "fa fa-plus-circle" aria-hidden = "true" > < / i > map additional port
< i class = "fa fa-plus-circle" aria-hidden = "true" > < / i > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.MAP_PORT" > < / por-translation >
< / span >
< / div >
< div class = "col-sm-12" style = "margin-top: 10px" ng-if = "state.selectedTemplate.Ports.length > 0" >
< span class = "small text-muted" > Portainer will automatically assign a port if you leave the host port empty. < / span >
< span class = "small text-muted" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.PORT_MAPPING.NOTE" > < / por-translation > < / span >
< / div >
<!-- !port - mapping -->
<!-- port - mapping - input - list -->
@ -99,7 +112,7 @@
< div ng-repeat = "portBinding in state.selectedTemplate.Ports" style = "margin-top: 2px;" >
<!-- host - port -->
< div class = "input-group col-sm-4 input-group-sm" >
< span class = "input-group-addon" > host < / span >
< span class = "input-group-addon" > < por-translation key = "COMMON.DOCKER.HOST" > < / por-translation > < / span >
< input type = "text" class = "form-control" ng-model = "portBinding.hostPort" placeholder = "e.g. 80 or 1.2.3.4:80 (optional)" >
< / div >
<!-- !host - port -->
@ -108,7 +121,7 @@
< / span >
<!-- container - port -->
< div class = "input-group col-sm-4 input-group-sm" >
< span class = "input-group-addon" > container < / span >
< span class = "input-group-addon" > < por-translation key = "COMMON.DOCKER.CONTAINER" > < / por-translation > < / span >
< input type = "text" class = "form-control" ng-model = "portBinding.containerPort" placeholder = "e.g. 80" >
< / div >
<!-- !container - port -->
@ -131,13 +144,15 @@
<!-- volume - mapping -->
< div class = "form-group" >
< div class = "col-sm-12" style = "margin-top: 5px;" >
< label class = "control-label text-left" > Volume mapping< / label >
< label class = "control-label text-left" >
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.LABEL" > < / por-translation >
< / label >
< span class = "label label-default interactive" style = "margin-left: 10px;" ng-click = "addVolume()" >
< i class = "fa fa-plus-circle" aria-hidden = "true" > < / i > map additional volume
< i class = "fa fa-plus-circle" aria-hidden = "true" > < / i > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.MAP_VOLUME" > < / por-translation >
< / span >
< / div >
< div class = "col-sm-12" style = "margin-top: 10px" ng-if = "state.selectedTemplate.Volumes.length > 0" >
< span class = "small text-muted" > Portainer will automatically create and map a local volume when using the < b > auto< / b > option. < / span >
< span class = "small text-muted" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.NOTE" > < / por-translation > < / span >
< / div >
< div ng-repeat = "volume in state.selectedTemplate.Volumes" >
< div class = "col-sm-12" style = "margin-top: 10px;" >
@ -145,16 +160,16 @@
< div class = "col-sm-12 form-inline" >
<!-- container - path -->
< div class = "input-group input-group-sm col-sm-6" >
< span class = "input-group-addon" > container < / span >
< span class = "input-group-addon" > < por-translation key = "COMMON.DOCKER.CONTAINER" > < / por-translation > < / span >
< input type = "text" class = "form-control" ng-model = "volume.containerPath" placeholder = "e.g. /path/in/container" >
< / div >
<!-- !container - path -->
<!-- volume - type -->
< div class = "input-group col-sm-5" style = "margin-left: 5px;" >
< div class = "btn-group btn-group-sm" >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'auto'" ng-click = "volume.name = ''" > Auto < / label >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'volume'" ng-click = "volume.name = ''" > Volume < / label >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'bind'" ng-click = "volume.name = ''" > Bind < / label >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'auto'" ng-click = "volume.name = ''" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.AUTO" > < / por-translation > < / label >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'volume'" ng-click = "volume.name = ''" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.VOLUME" > < / por-translation > < / label >
< label class = "btn btn-primary" ng-model = "volume.type" uib-btn-radio = "'bind'" ng-click = "volume.name = ''" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.TYPE.BIND" > < / por-translation > < / label >
< / div >
< button class = "btn btn-sm btn-danger" type = "button" ng-click = "removeVolume($index)" >
< i class = "fa fa-trash" aria-hidden = "true" > < / i >
@ -168,24 +183,24 @@
< i class = "fa fa-long-arrow-right" aria-hidden = "true" > < / i >
<!-- volume -->
< div class = "input-group input-group-sm col-sm-6" ng-if = "volume.type === 'volume'" >
< span class = "input-group-addon" > volume < / span >
< span class = "input-group-addon" > < por-translation key = "COMMON.DOCKER.VOLUME" > < / por-translation > < / span >
< select class = "form-control" ng-model = "volume.name" >
< option selected disabled hidden value = "" > Select a volume< / option >
< option selected disabled hidden value = "" translate > TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.SELECT_VOLUME < / option >
< option ng-repeat = "vol in availableVolumes" ng-value = "vol.Name" > {{ vol.Name|truncate:30}}< / option >
< / select >
< / div >
<!-- !volume -->
<!-- bind -->
< div class = "input-group input-group-sm col-sm-6" ng-if = "volume.type === 'bind'" >
< span class = "input-group-addon" > host < / span >
< span class = "input-group-addon" > < por-translation key = "COMMON.DOCKER.HOST" > < / por-translation > < / span >
< input type = "text" class = "form-control" ng-model = "volume.name" placeholder = "e.g. /path/on/host" >
< / div >
<!-- !bind -->
<!-- read - only -->
< div class = "input-group input-group-sm col-sm-5" style = "margin-left: 5px;" >
< div class = "btn-group btn-group-sm" >
< label class = "btn btn-primary" ng-model = "volume.readOnly" uib-btn-radio = "false" > Writable < / label >
< label class = "btn btn-primary" ng-model = "volume.readOnly" uib-btn-radio = "true" > Read-only < / label >
< label class = "btn btn-primary" ng-model = "volume.readOnly" uib-btn-radio = "false" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.WRITABLE" > < / por-translation > < / label >
< label class = "btn btn-primary" ng-model = "volume.readOnly" uib-btn-radio = "true" > < por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ADVANCED_OPTIONS.VOLUME_MAPPING.READONLY" > < / por-translation > < / label >
< / div >
< / div >
<!-- !read - only -->
@ -200,14 +215,16 @@
<!-- actions -->
< div class = "form-group" >
< div class = "col-sm-12" >
< button type = "button" class = "btn btn-primary btn-sm" ng-disabled = "!formValues.network" ng-click = "createTemplate()" > Create < / button >
< button type = "button" class = "btn btn-primary btn-sm" ng-disabled = "!formValues.network" ng-click = "createTemplate()" > < por-translation key = "COMMON.VERBS.CREATE" > < / por-translation > < / button >
< i id = "createContainerSpinner" class = "fa fa-cog fa-spin" style = "margin-left: 5px; display: none;" > < / i >
< span class = "small text-muted" style = "margin-left: 10px" ng-if = " globalNe two rkCo unt === 0 && applicationStat e.endpoint.mode.provider === 'DOCKER_SWARM' && !state.formValidationError ">
When using Swarm, we recommend deploying containers in a shared network. Looks like you don't have any shared network, head over the < a ui-sref = "networks" > networks view< / a > to create one.
< span class = "small text-muted" style = "margin-left: 10px" ng-if = " true">
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ACTIONS.SWARM_NOTE_NETWORK" compile = "true" > < / por-translation >
< / span >
< span ng-if = "applicationState.endpoint.mode.provider === 'DOCKER_SWARM_MODE' && !state.formValidationError" style = "margin-left: 10px" >
< i class = "fa fa-exclamation-triangle" aria-hidden = "true" > < / i >
< span class = "small text-muted" style = "margin-left: 5px;" > App templates cannot be deployed as Swarm Mode services for the moment. You can still use them to quickly deploy containers on the Docker host.< / span >
< span class = "small text-muted" style = "margin-left: 5px;" >
< por-translation key = "TEMPLATES.SELECTED_TEMPLATE.FORM.ACTIONS.SWARM_NOTE_STACK" > < / por-translation >
< / span >
< / span >
< span class = "text-danger" ng-if = "state.formValidationError" style = "margin-left: 5px;" > {{ state.formValidationError }}< / span >
< / div >
@ -223,9 +240,9 @@
< rd-template-widget >
< rd-widget-header icon = "fa-rocket" title = "Templates" >
< div ng-if = "availableCategories.length > 0" class = "pull-right" >
Category
< por-translation key = "TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.CATEGORY" > < / por-translation >
< select ng-model = "state.filters.Categories" >
< option value = "!" > All< / option >
< option value = "!" translate > COMMON.UI.ALL < / option >
< option ng-repeat = "category in availableCategories" value = "{{ category }}" > {{ category }}< / option >
< / select >
< / div >
@ -235,15 +252,15 @@
<!-- Platform -->
< span class = "btn-group btn-group-sm" style = "margin-right: 15px;" >
< label class = "btn btn-primary" ng-model = "state.filters.Platform" uib-btn-radio = "'!'" >
All
< por-translation key = "COMMON.UI.ALL" > < / por-translation >
< / label >
< label class = "btn btn-primary" ng-model = "state.filters.Platform" uib-btn-radio = "'windows'" >
< i class = "fa fa-windows" aria-hidden = "true" > < / i >
Windows
< por-translation key = "TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.PLATFORM_FILTERS.WINDOWS" > < / por-translation >
< / label >
< label class = "btn btn-primary" ng-model = "state.filters.Platform" uib-btn-radio = "'linux'" >
< i class = "fa fa-linux" aria-hidden = "true" > < / i >
Linux
< por-translation key = "TEMPLATES.WIDGET_TEMPLATE_LIST.HEADER.PLATFORM_FILTERS.LINUX" > < / por-translation >
< / label >
< / span >
< / div >
@ -288,10 +305,10 @@
<!-- !template -->
< / div >
< div ng-if = "!templates" class = "text-center text-muted" >
Loading...
< por-translation key = "COMMON.UI.LOADING" > < / por-translation >
< / div >
< div ng-if = "(templates | filter:state.filters:true).length == 0" class = "text-center text-muted" >
No templates available.
< por-translation key = "TEMPLATES.WIDGET_TEMPLATE_LIST.LIST.EMPTY" > < / por-translation >
< / div >
< / div >
< / rd-widget-body >