mirror of https://github.com/portainer/portainer
feat(ui): ui-improvements-helm EE-3476 (#7344)
* feat(ui): helm views ui update EE-3476pull/7381/head
parent
e28a1491d4
commit
57e53d1a21
|
@ -99,6 +99,9 @@ pr-icon {
|
|||
}
|
||||
|
||||
.icon-nested-gray {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
padding: 5px;
|
||||
|
@ -109,6 +112,9 @@ pr-icon {
|
|||
}
|
||||
|
||||
.icon-nested-blue {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
padding: 5px;
|
||||
|
|
|
@ -96,7 +96,7 @@ div.input-mask {
|
|||
}
|
||||
.widget .widget-header {
|
||||
color: var(--text-widget-header-color);
|
||||
padding: 10px 15px;
|
||||
padding: 20px 20px 10px 20px;
|
||||
line-height: 30px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
|
|
@ -234,6 +234,27 @@ json-tree .branch-preview {
|
|||
background-color: var(--bg-progress-color);
|
||||
}
|
||||
|
||||
.ui-select-search,
|
||||
.ui-select-toggle {
|
||||
height: 30px;
|
||||
min-width: 260px;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
.ui-select-toggle {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
|
||||
.ui-select-match-text {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ui-select-match-text > a {
|
||||
verical-align: middle;
|
||||
}
|
||||
|
||||
.ui-select-bootstrap .ui-select-choices-row > span {
|
||||
color: var(--text-ui-select-color);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<svg width="100" height="100" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M37.5 25.0002V43.7552C37.5 46.0507 37.5 47.1985 37.2138 48.2621C36.9603 49.2044 36.5432 50.095 35.9816 50.893C35.3477 51.7938 34.4659 52.5286 32.7025 53.9981L17.2975 66.8356C15.5341 68.3051 14.6523 69.0399 14.0184 69.9406C13.4568 70.7387 13.0397 71.6292 12.7862 72.5716C12.5 73.6352 12.5 74.783 12.5 77.0785V78.3335C12.5 83.0006 12.5 85.3342 13.4083 87.1168C14.2072 88.6848 15.4821 89.9596 17.0501 90.7586C18.8327 91.6668 21.1662 91.6668 25.8333 91.6668H74.1667C78.8338 91.6668 81.1673 91.6668 82.9499 90.7586C84.5179 89.9596 85.7928 88.6848 86.5917 87.1168C87.5 85.3342 87.5 83.0006 87.5 78.3335V77.0785C87.5 74.783 87.5 73.6352 87.2138 72.5716C86.9603 71.6292 86.5432 70.7387 85.9816 69.9406C85.3477 69.0399 84.4659 68.3051 82.7025 66.8356L67.2975 53.9981C65.5341 52.5286 64.6523 51.7938 64.0184 50.893C63.4568 50.095 63.0397 49.2044 62.7861 48.2621C62.5 47.1985 62.5 46.0507 62.5 43.7552V25.0002M34.5833 25.0002H65.4167C66.5834 25.0002 67.1668 25.0002 67.6125 24.7731C68.0045 24.5734 68.3232 24.2546 68.5229 23.8626C68.75 23.417 68.75 22.8336 68.75 21.6668V11.6668C68.75 10.5001 68.75 9.91667 68.5229 9.47102C68.3232 9.07901 68.0045 8.7603 67.6125 8.56057C67.1668 8.3335 66.5834 8.3335 65.4167 8.3335H34.5833C33.4166 8.3335 32.8332 8.3335 32.3875 8.56057C31.9955 8.7603 31.6768 9.07901 31.4771 9.47102C31.25 9.91667 31.25 10.5001 31.25 11.6668V21.6668C31.25 22.8336 31.25 23.417 31.4771 23.8626C31.6768 24.2546 31.9955 24.5734 32.3875 24.7731C32.8332 25.0002 33.4166 25.0002 34.5833 25.0002ZM22.9167 70.8335H77.0833C79.0194 70.8335 79.9874 70.8335 80.7924 70.9936C84.0982 71.6512 86.6823 74.2353 87.3399 77.5411C87.5 78.3461 87.5 79.3141 87.5 81.2502C87.5 83.1862 87.5 84.1543 87.3399 84.9593C86.6823 88.265 84.0982 90.8492 80.7924 91.5067C79.9874 91.6668 79.0194 91.6668 77.0833 91.6668H22.9167C20.9806 91.6668 20.0126 91.6668 19.2076 91.5067C15.9018 90.8492 13.3177 88.265 12.6601 84.9593C12.5 84.1543 12.5 83.1862 12.5 81.2502C12.5 79.3141 12.5 78.3461 12.6601 77.5411C13.3177 74.2353 15.9018 71.6512 19.2076 70.9936C20.0126 70.8335 20.9806 70.8335 22.9167 70.8335Z" stroke="black" stroke-width="8.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
<svg width="auto" height="auto" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M37.5 25.0002V43.7552C37.5 46.0507 37.5 47.1985 37.2138 48.2621C36.9603 49.2044 36.5432 50.095 35.9816 50.893C35.3477 51.7938 34.4659 52.5286 32.7025 53.9981L17.2975 66.8356C15.5341 68.3051 14.6523 69.0399 14.0184 69.9406C13.4568 70.7387 13.0397 71.6292 12.7862 72.5716C12.5 73.6352 12.5 74.783 12.5 77.0785V78.3335C12.5 83.0006 12.5 85.3342 13.4083 87.1168C14.2072 88.6848 15.4821 89.9596 17.0501 90.7586C18.8327 91.6668 21.1662 91.6668 25.8333 91.6668H74.1667C78.8338 91.6668 81.1673 91.6668 82.9499 90.7586C84.5179 89.9596 85.7928 88.6848 86.5917 87.1168C87.5 85.3342 87.5 83.0006 87.5 78.3335V77.0785C87.5 74.783 87.5 73.6352 87.2138 72.5716C86.9603 71.6292 86.5432 70.7387 85.9816 69.9406C85.3477 69.0399 84.4659 68.3051 82.7025 66.8356L67.2975 53.9981C65.5341 52.5286 64.6523 51.7938 64.0184 50.893C63.4568 50.095 63.0397 49.2044 62.7861 48.2621C62.5 47.1985 62.5 46.0507 62.5 43.7552V25.0002M34.5833 25.0002H65.4167C66.5834 25.0002 67.1668 25.0002 67.6125 24.7731C68.0045 24.5734 68.3232 24.2546 68.5229 23.8626C68.75 23.417 68.75 22.8336 68.75 21.6668V11.6668C68.75 10.5001 68.75 9.91667 68.5229 9.47102C68.3232 9.07901 68.0045 8.7603 67.6125 8.56057C67.1668 8.3335 66.5834 8.3335 65.4167 8.3335H34.5833C33.4166 8.3335 32.8332 8.3335 32.3875 8.56057C31.9955 8.7603 31.6768 9.07901 31.4771 9.47102C31.25 9.91667 31.25 10.5001 31.25 11.6668V21.6668C31.25 22.8336 31.25 23.417 31.4771 23.8626C31.6768 24.2546 31.9955 24.5734 32.3875 24.7731C32.8332 25.0002 33.4166 25.0002 34.5833 25.0002ZM22.9167 70.8335H77.0833C79.0194 70.8335 79.9874 70.8335 80.7924 70.9936C84.0982 71.6512 86.6823 74.2353 87.3399 77.5411C87.5 78.3461 87.5 79.3141 87.5 81.2502C87.5 83.1862 87.5 84.1543 87.3399 84.9593C86.6823 88.265 84.0982 90.8492 80.7924 91.5067C79.9874 91.6668 79.0194 91.6668 77.0833 91.6668H22.9167C20.9806 91.6668 20.0126 91.6668 19.2076 91.5067C15.9018 90.8492 13.3177 88.265 12.6601 84.9593C12.5 84.1543 12.5 83.1862 12.5 81.2502C12.5 79.3141 12.5 78.3461 12.6601 77.5411C13.3177 74.2353 15.9018 71.6512 19.2076 70.9936C20.0126 70.8335 20.9806 70.8335 22.9167 70.8335Z" stroke="currentColor" stroke-width="8.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,10 @@
|
|||
<svg width="auto" height="auto" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2026_8347)">
|
||||
<path d="M2.03394 12.0799L21.9659 12.0799M4.05923 7.91314C4.44428 7.25611 4.90783 6.65064 5.437 6.10964M5.437 6.10964C7.12201 4.38695 9.4724 3.31777 12.0725 3.31777C14.6331 3.31777 16.9516 4.35473 18.6308 6.03161M5.437 6.10964L3.87003 4.54238M5.437 6.10964L5.44586 6.1185M18.6308 6.03161C19.1922 6.59221 19.6821 7.22434 20.0858 7.91314M18.6308 6.03161L20.1869 4.47547M18.6308 6.03161L18.6243 6.03807M11.9948 1.04492L11.9948 3.31804M19.969 16.069C19.584 16.726 19.1204 17.3315 18.5912 17.8725M18.5912 17.8725C16.9062 19.5952 14.5559 20.6643 11.9557 20.6643C9.39512 20.6643 7.07669 19.6274 5.39746 17.9505M18.5912 17.8725L20.1582 19.4397M18.5912 17.8725L18.5824 17.8636M5.39746 17.9505C4.83608 17.3899 4.34614 16.7578 3.94248 16.069M5.39746 17.9505L3.84132 19.5066M5.39746 17.9505L5.40392 17.944M12.0335 22.9372L12.0335 20.6641" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2026_8347">
|
||||
<rect width="24" height="24" fill="white" transform="translate(24) rotate(90)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,5 +1,10 @@
|
|||
<rd-widget>
|
||||
<rd-widget-header icon="fa-dharmachakra" title-text="Additional repositories"></rd-widget-header>
|
||||
<div class="toolBar px-5 pt-5">
|
||||
<div class="toolBarTitle">
|
||||
<pr-icon icon="'svg-helm'" class-name="'icon-nested-blue'" mode="'primary'"></pr-icon>
|
||||
Additional repositories
|
||||
</div>
|
||||
</div>
|
||||
<rd-widget-body>
|
||||
<div class="actionBar">
|
||||
<form class="form-horizontal" name="addUserHelmRepoForm">
|
||||
|
@ -7,7 +12,7 @@
|
|||
<span class="col-sm-12 text-muted small"> Add a Helm repository. All Helm charts in the repository will be added to the list. </span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-group mb-2">
|
||||
<div class="col-sm-12">
|
||||
<input
|
||||
type="url"
|
||||
|
@ -22,16 +27,20 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group nomargin" ng-show="addUserHelmRepoForm.repo.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div class="small">
|
||||
<div ng-messages="addUserHelmRepoForm.repo.$error">
|
||||
<p ng-message="pattern"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> A valid URL beginning with http(s) is required.</p>
|
||||
<p class="vertical-center" ng-message="pattern"
|
||||
><pr-icon icon="'alert-triangle'" feather="true" mode="'warning'"></pr-icon> A valid URL beginning with http(s) is required.</p
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-show="$ctrl.doesRepoExist()">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div> <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Helm repo already exists. </div>
|
||||
<div class="form-group nomargin" ng-show="$ctrl.doesRepoExist()">
|
||||
<div class="small">
|
||||
<div ng-messages="addUserHelmRepoForm.repo.$error">
|
||||
<p class="vertical-center"><pr-icon icon="'alert-triangle'" feather="true" mode="'warning'"></pr-icon> Helm repo already exists.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -39,7 +48,7 @@
|
|||
<div class="col-sm-12">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-default nomargin"
|
||||
class="btn btn-primary btn-sm nomargin"
|
||||
ng-click="$ctrl.addRepository()"
|
||||
ng-disabled="$ctrl.state.isAddingRepo || addUserHelmRepoForm.repo.$invalid || $ctrl.doesRepoExist()"
|
||||
analytics-on
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
<!-- helm chart -->
|
||||
<div ng-class="{ 'blocklist-item--selected': $ctrl.model.Selected }" class="blocklist-item template-item" ng-click="$ctrl.onSelect($ctrl.model)">
|
||||
<div ng-class="{ 'blocklist-item--selected': $ctrl.model.Selected }" class="blocklist-item template-item mx-[10px]" ng-click="$ctrl.onSelect($ctrl.model)">
|
||||
<div class="blocklist-item-box">
|
||||
<!-- helmchart-image -->
|
||||
<span ng-if="$ctrl.model.icon">
|
||||
<img class="blocklist-item-logo" ng-src="{{ $ctrl.model.icon }}" />
|
||||
<fallback-image
|
||||
src="$ctrl.model.icon"
|
||||
fallback-icon="'svg-helm'"
|
||||
class-name="'blocklist-item-logo h-16 w-auto'"
|
||||
fallback-class-name="'icon-nested-blue !h-12 !w-12'"
|
||||
fallback-mode="'primary'"
|
||||
size="'xl'"
|
||||
></fallback-image>
|
||||
</span>
|
||||
<span class="blocklist-item-logo" ng-if="!$ctrl.model.icon">
|
||||
<i class="fa fa-dharmachakra fa-4x blue-icon" aria-hidden="true"></i>
|
||||
<span class="blocklist-item-logo vertical-center" ng-if="!$ctrl.model.icon">
|
||||
<pr-icon icon="'svg-helm'" mode="'primary'" class-name="'icon-nested-blue'"></pr-icon>
|
||||
</span>
|
||||
<!-- !helmchart-image -->
|
||||
<!-- helmchart-details -->
|
||||
|
@ -18,8 +25,8 @@
|
|||
{{ $ctrl.model.name }}
|
||||
</span>
|
||||
<span class="space-left blocklist-item-subtitle">
|
||||
<span>
|
||||
<i class="fa fa-dharmachakra" aria-hidden="true"></i>
|
||||
<span class="vertical-center">
|
||||
<pr-icon icon="'svg-helm'" mode="'primary'"></pr-icon>
|
||||
</span>
|
||||
<span> Helm </span>
|
||||
</span>
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
<div class="datatable">
|
||||
<rd-widget>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<div class="toolBar">
|
||||
<div class="toolBarTitle"> <pr-icon icon="$ctrl.titleIcon" class-name="space-right"></pr-icon> {{ $ctrl.titleText }} </div>
|
||||
</div>
|
||||
|
||||
<div class="actionBar">
|
||||
<div>
|
||||
<span style="width: 25%">
|
||||
<ui-select ng-model="$ctrl.state.selectedCategory" theme="bootstrap">
|
||||
<ui-select-match placeholder="Select a category">
|
||||
<a class="btn btn-xs btn-link pull-right" ng-click="$ctrl.clearCategory()"><i class="glyphicon glyphicon-remove"></i></a>
|
||||
<span>{{ $select.selected }}</span>
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="category in ($ctrl.state.categories | filter: $select.search)">
|
||||
<span>{{ category }}</span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</span>
|
||||
<div class="toolBar vertical-center !gap-x-5 !gap-y-1 flex-wrap w-full relative">
|
||||
<div class="toolBarTitle vertical-center">
|
||||
<pr-icon icon="$ctrl.titleIcon" feather="true" mode="'primary'" class-name="'icon-nested-blue space-right'"></pr-icon>
|
||||
{{ $ctrl.titleText }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="searchBar" style="border-top: 2px solid #f6f6f6">
|
||||
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
|
||||
<input
|
||||
type="text"
|
||||
class="searchInput"
|
||||
ng-model="$ctrl.state.textFilter"
|
||||
ng-change="$ctrl.onTextFilterChange()"
|
||||
placeholder="Search..."
|
||||
auto-focus
|
||||
ng-model-options="{ debounce: 300 }"
|
||||
/>
|
||||
<div class="searchBar vertical-center !mr-0">
|
||||
<pr-icon icon="'search'" feather="true" class="searchIcon"></pr-icon>
|
||||
<input
|
||||
type="text"
|
||||
class="searchInput"
|
||||
ng-model="$ctrl.state.textFilter"
|
||||
ng-change="$ctrl.onTextFilterChange()"
|
||||
placeholder="Search..."
|
||||
auto-focus
|
||||
ng-model-options="{ debounce: 300 }"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<ui-select ng-model="$ctrl.state.selectedCategory" theme="bootstrap" append-to-body="true">
|
||||
<ui-select-match placeholder="Select a category">
|
||||
<a class="btn btn-xs btn-link pull-right vertical-center" ng-click="$ctrl.clearCategory()">
|
||||
<pr-icon icon="'x'" feather="true"></pr-icon>
|
||||
</a>
|
||||
<span class="vertical-center">{{ $select.selected }}</span>
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="category in ($ctrl.state.categories | filter: $select.search)">
|
||||
<span>{{ category }}</span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="blocklist">
|
||||
|
|
|
@ -83,7 +83,7 @@ export default class HelmTemplatesController {
|
|||
}
|
||||
|
||||
async selectHelmChart(chart) {
|
||||
this.$anchorScroll('view-top');
|
||||
window.scrollTo(0, 0);
|
||||
this.state.showCustomValues = false;
|
||||
this.state.chart = chart;
|
||||
await this.getHelmValues();
|
||||
|
|
|
@ -2,14 +2,19 @@
|
|||
|
||||
<information-panel title-text="Information" ng-if="!$ctrl.state.chart">
|
||||
<span class="small text-muted">
|
||||
<p>
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
This is a first version for Helm charts, for more information see this <a href="https://www.portainer.io/blog/portainer-now-with-helm-support" target="_blank">blog post</a>.
|
||||
</p>
|
||||
<p ng-if="$ctrl.state.globalRepository === ''">
|
||||
<i class="fa fa-exclamation-circle blue-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
<p class="inline-flex flex-row items-center">
|
||||
<pr-icon icon="'info'" feather="true" class="mr-1 vertical-center" mode="'primary'"></pr-icon>
|
||||
This is a first version for Helm charts, for more information see this <a
|
||||
class="text-blue-8 hover:underline hover:text-blue-8"
|
||||
href="https://www.portainer.io/blog/portainer-now-with-helm-support"
|
||||
target="_blank"
|
||||
>blog post</a
|
||||
>.</p
|
||||
>
|
||||
<p ng-if="$ctrl.state.globalRepository === ''" class="inline-flex items-center">
|
||||
<pr-icon icon="'info'" feather="true"></pr-icon>
|
||||
<span>The Global Helm Repository is not configured.</span>
|
||||
<a ng-if="$ctrl.state.isAdmin" ui-sref="portainer.settings">Configure Global Helm Repository in Settings</a>
|
||||
<a ng-if="$ctrl.state.isAdmin" ui-sref="portainer.settings">Configure Global Helm Repository in Settings</a>.
|
||||
</p>
|
||||
</span>
|
||||
</information-panel>
|
||||
|
@ -18,7 +23,16 @@
|
|||
<!-- helmchart-form -->
|
||||
<div class="col-sm-12" ng-if="$ctrl.state.chart">
|
||||
<rd-widget>
|
||||
<rd-widget-custom-header icon="$ctrl.state.chart.icon" title-text="$ctrl.state.chart.name"></rd-widget-custom-header>
|
||||
<div class="toolBarTitle vertical-center pt-5 px-5 text-muted">
|
||||
<fallback-image
|
||||
src="$ctrl.state.chart.icon"
|
||||
fallback-icon="'svg-helm'"
|
||||
class-name="'h-8 w-8'"
|
||||
fallback-class-name="'icon-nested-blue'"
|
||||
fallback-mode="'primary'"
|
||||
></fallback-image>
|
||||
{{ $ctrl.state.chart.name }}
|
||||
</div>
|
||||
<rd-widget-body classes="padding">
|
||||
<form class="form-horizontal" name="$ctrl.helmTemplateCreationForm">
|
||||
<!-- description -->
|
||||
|
@ -26,7 +40,7 @@
|
|||
<div class="col-sm-12 form-section-title"> Description </div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="template-note" ng-bind-html="$ctrl.state.chart.description"></div>
|
||||
<div class="text-xs text-muted" ng-bind-html="$ctrl.state.chart.description"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -46,17 +60,16 @@
|
|||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="!$ctrl.state.resourcePool">
|
||||
<div class="col-sm-12 small text-muted">
|
||||
<i class="fa fa-exclamation-circle orange-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
<div class="col-sm-12 small text-muted vertical-center">
|
||||
<pr-icon icon="'alert-triangle'" feather="true" mode="'warning'"></pr-icon>
|
||||
You do not have access to any namespace. Contact your administrator to get access to a namespace.
|
||||
</div>
|
||||
</div>
|
||||
<!-- !namespace-input -->
|
||||
<!-- name-input -->
|
||||
<div class="form-group">
|
||||
<label for="release_name" class="col-sm-2 control-label text-left">Name</label>
|
||||
<div class="form-group mb-2">
|
||||
<label for="release_name" class="col-sm-2 control-label text-left required">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input
|
||||
type="text"
|
||||
|
@ -70,12 +83,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="$ctrl.helmTemplateCreationForm.release_name.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div class="small">
|
||||
<div ng-messages="$ctrl.helmTemplateCreationForm.release_name.$error">
|
||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||
<p ng-message="pattern">
|
||||
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field must consist of lower case alphanumeric characters or '-', start with an alphabetic
|
||||
character, and end with an alphanumeric character (e.g. 'my-name', or 'abc-123').
|
||||
<div class="col-sm-2"></div>
|
||||
<p class="vertical-center col-sm-10 text-muted" ng-message="required">
|
||||
<pr-icon icon="'alert-triangle'" feather="true" mode="'warning'" class="vertical-center"></pr-icon>
|
||||
This field is required.
|
||||
</p>
|
||||
<p class="vertical-center col-sm-10 text-muted" ng-message="pattern">
|
||||
<pr-icon icon="'alert-triangle'" feather="true" mode="'warning'" class="vertical-center"></pr-icon>
|
||||
This field must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character (e.g. 'my-name',
|
||||
or 'abc-123').
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,35 +101,44 @@
|
|||
<!-- !name-input -->
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<a class="small interactive" ng-if="!$ctrl.state.showCustomValues && !$ctrl.state.loadingValues" ng-click="$ctrl.state.showCustomValues = true;">
|
||||
<i class="fa fa-plus space-right" aria-hidden="true"></i> Show custom values
|
||||
</a>
|
||||
<span class="small interactive" ng-if="$ctrl.state.loadingValues"> <i class="fa fa-sync-alt space-right" aria-hidden="true"></i> Loading values.yaml... </span>
|
||||
<a class="small interactive" ng-if="$ctrl.state.showCustomValues" ng-click="$ctrl.state.showCustomValues = false;">
|
||||
<i class="fa fa-minus space-right" aria-hidden="true"></i> Hide custom values
|
||||
</a>
|
||||
<button
|
||||
ng-if="!$ctrl.state.showCustomValues && !$ctrl.state.loadingValues"
|
||||
class="btn btn-xs btn-default vertical-center mr-2 !ml-0"
|
||||
ng-click="$ctrl.state.showCustomValues = true;"
|
||||
>
|
||||
<pr-icon icon="'plus'" feather="true" class="vertical-center"></pr-icon>
|
||||
Show custom values
|
||||
</button>
|
||||
<span class="small interactive vertical-center" ng-if="$ctrl.state.loadingValues">
|
||||
<pr-icon icon="'refresh-cw'" class="mr-1" feather="true"></pr-icon>
|
||||
Loading values.yaml...
|
||||
</span>
|
||||
<button ng-if="$ctrl.state.showCustomValues" class="btn btn-xs btn-default vertical-center mr-2 !ml-0" ng-click="$ctrl.state.showCustomValues = false;">
|
||||
<pr-icon icon="'minus'" feather="true" class="vertical-center"></pr-icon>
|
||||
Hide custom values
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- values override -->
|
||||
<div ng-if="$ctrl.state.showCustomValues">
|
||||
<!-- web-editor -->
|
||||
<div>
|
||||
<div class="col-sm-12 form-section-title"> Web editor </div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can get more information about Helm values file format in the
|
||||
<a href="https://helm.sh/docs/chart_template_guide/values_files/" target="_blank">official documentation</a>.
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<code-editor
|
||||
<web-editor-form
|
||||
identifier="helm-app-creation-editor"
|
||||
placeholder="# Define or paste the content of your values yaml file here"
|
||||
yml="true"
|
||||
on-change="($ctrl.editorUpdate)"
|
||||
value="$ctrl.state.values"
|
||||
></code-editor>
|
||||
on-change="($ctrl.editorUpdate)"
|
||||
yml="true"
|
||||
placeholder="# Define or paste the content of your values yaml file here"
|
||||
>
|
||||
<editor-description>
|
||||
You can get more information about Helm values file format in the
|
||||
<a href="https://helm.sh/docs/chart_template_guide/values_files/" target="_blank" class="text-blue-8 hover:text-blue-8 hover:underline"
|
||||
>official documentation</a
|
||||
>.
|
||||
</editor-description>
|
||||
</web-editor-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -124,7 +151,7 @@
|
|||
<div class="col-sm-12">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm"
|
||||
class="btn btn-primary btn-sm !ml-0"
|
||||
ng-disabled="!($ctrl.state.appName && $ctrl.state.resourcePool && !$ctrl.state.loadingValues && !$ctrl.state.actionInProgress)"
|
||||
ng-click="$ctrl.installHelmchart()"
|
||||
button-spinner="$ctrl.state.actionInProgress"
|
||||
|
@ -155,7 +182,7 @@
|
|||
<div class="col-sm-12">
|
||||
<helm-templates-list
|
||||
title-text="Charts"
|
||||
title-icon="fa-rocket"
|
||||
title-icon="compass"
|
||||
charts="$ctrl.state.charts"
|
||||
table-key="$ctrl.state.charts"
|
||||
select-action="$ctrl.selectHelmChart"
|
||||
|
|
|
@ -9,35 +9,37 @@
|
|||
|
||||
<div ng-if="$ctrl.state.viewReady">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="col-sm-12 form-section-title"> Information </div>
|
||||
<p class="text-muted">
|
||||
<i class="fa fa-flask orange-icon" aria-hidden="true" style="margin-right: 2px"></i>
|
||||
This is a first version for Helm charts, for more information see this
|
||||
<a href="https://www.portainer.io/blog/portainer-now-with-helm-support" target="_blank">blog post</a>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-12">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="fa-dharmachakra" title-text="Release"></rd-widget-header>
|
||||
<rd-widget-body classes="no-padding">
|
||||
<div class="toolBar vertical-center !gap-x-5 !gap-y-1 p-5 flex-wrap w-full">
|
||||
<div class="toolBarTitle vertical-center">
|
||||
<pr-icon icon="'svg-helm'" class-name="'icon-nested-blue'" mode="'primary'"></pr-icon>
|
||||
Release
|
||||
</div>
|
||||
</div>
|
||||
<div class="toolBarTitle text-muted small vertical-center px-5 !gap-0">
|
||||
<pr-icon icon="'info'" feather="true" mode="'primary'" class-name="'!mr-1'" class="vertical-center"></pr-icon>
|
||||
This is a first version for Helm charts, for more information see this
|
||||
<a href="https://www.portainer.io/blog/portainer-now-with-helm-support" target="_blank" class="text-blue-8 hover:text-blue-8 hover:underline">blog post</a>.
|
||||
</div>
|
||||
<rd-widget-body>
|
||||
<table class="table">
|
||||
<tbody class="release-table">
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>
|
||||
<td class="vertical-center !pl-0">Name</td>
|
||||
<td class="vertical-center !p-2">
|
||||
{{ $ctrl.state.release.name }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Chart</td>
|
||||
<td>
|
||||
<td class="vertical-center !pl-0">Chart</td>
|
||||
<td class="vertical-center !p-2">
|
||||
{{ $ctrl.state.release.chart }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>App version</td>
|
||||
<td>
|
||||
<td class="vertical-center !pl-0">App version</td>
|
||||
<td class="vertical-center !p-2">
|
||||
{{ $ctrl.state.release.app_version }}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Tooltip } from '@@/Tip/Tooltip';
|
|||
import { TableColumnHeaderAngular } from '@@/datatables/TableHeaderCell';
|
||||
import { DashboardItem } from '@@/DashboardItem';
|
||||
import { SearchBar } from '@@/datatables/SearchBar';
|
||||
import { FallbackImage } from '@@/FallbackImage';
|
||||
|
||||
import { fileUploadField } from './file-upload-field';
|
||||
import { switchField } from './switch-field';
|
||||
|
@ -50,6 +51,19 @@ export const componentsModule = angular
|
|||
'pageHeader',
|
||||
r2a(PageHeader, ['title', 'breadcrumbs', 'loading', 'onReload', 'reload'])
|
||||
)
|
||||
.component(
|
||||
'fallbackImage',
|
||||
r2a(FallbackImage, [
|
||||
'src',
|
||||
'fallbackIcon',
|
||||
'alt',
|
||||
'size',
|
||||
'className',
|
||||
'fallbackMode',
|
||||
'fallbackClassName',
|
||||
'feather',
|
||||
])
|
||||
)
|
||||
.component(
|
||||
'prIcon',
|
||||
react2angular(Icon, ['className', 'feather', 'icon', 'mode', 'size'])
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import clsx from 'clsx';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Icon, IconMode, IconSize } from './Icon';
|
||||
|
||||
interface Props {
|
||||
// props for the image to load
|
||||
src: string; // a link to an external image
|
||||
fallbackIcon: string;
|
||||
alt?: string;
|
||||
size?: IconSize;
|
||||
className?: string;
|
||||
// additional fallback icon props
|
||||
fallbackMode?: IconMode;
|
||||
fallbackClassName?: string;
|
||||
feather?: boolean;
|
||||
}
|
||||
|
||||
export function FallbackImage({
|
||||
src,
|
||||
fallbackIcon,
|
||||
alt,
|
||||
size,
|
||||
className,
|
||||
fallbackMode,
|
||||
fallbackClassName,
|
||||
feather,
|
||||
}: Props) {
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
const classes = clsx(className, { [`icon-${size}`]: size });
|
||||
|
||||
useEffect(() => {
|
||||
setError(false);
|
||||
}, [src]);
|
||||
|
||||
if (!error) {
|
||||
return (
|
||||
<img
|
||||
className={classes}
|
||||
src={src}
|
||||
alt={alt}
|
||||
onError={() => setError(true)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// fallback icon if there is an error loading the image
|
||||
return (
|
||||
<Icon
|
||||
icon={fallbackIcon}
|
||||
feather={feather}
|
||||
className={fallbackClassName}
|
||||
size={size}
|
||||
mode={fallbackMode}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -10,23 +10,27 @@ export interface IconProps {
|
|||
featherIcon?: boolean;
|
||||
}
|
||||
|
||||
export type IconMode =
|
||||
| 'alt'
|
||||
| 'primary'
|
||||
| 'primary-alt'
|
||||
| 'secondary'
|
||||
| 'secondary-alt'
|
||||
| 'warning'
|
||||
| 'warning-alt'
|
||||
| 'danger'
|
||||
| 'danger-alt'
|
||||
| 'success'
|
||||
| 'success-alt';
|
||||
|
||||
export type IconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
interface Props {
|
||||
icon: ReactNode | ComponentType<{ size?: string | number }>;
|
||||
feather?: boolean;
|
||||
className?: string;
|
||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
mode?:
|
||||
| 'alt'
|
||||
| 'primary'
|
||||
| 'primary-alt'
|
||||
| 'secondary'
|
||||
| 'secondary-alt'
|
||||
| 'warning'
|
||||
| 'warning-alt'
|
||||
| 'danger'
|
||||
| 'danger-alt'
|
||||
| 'success'
|
||||
| 'success-alt';
|
||||
size?: IconSize;
|
||||
mode?: IconMode;
|
||||
}
|
||||
|
||||
export function Icon({ icon, feather, className, mode, size }: Props) {
|
||||
|
|
|
@ -59,6 +59,7 @@ import gitlab from '@/assets/ico/vendor/gitlab.svg?c';
|
|||
import google from '@/assets/ico/vendor/google.svg?c';
|
||||
import googlecloud from '@/assets/ico/vendor/googlecloud.svg?c';
|
||||
import kubernetes from '@/assets/ico/vendor/kubernetes.svg?c';
|
||||
import helm from '@/assets/ico/vendor/helm.svg?c';
|
||||
import linode from '@/assets/ico/vendor/linode.svg?c';
|
||||
import microsoft from '@/assets/ico/vendor/microsoft.svg?c';
|
||||
import nomad from '@/assets/ico/vendor/nomad.svg?c';
|
||||
|
@ -66,6 +67,8 @@ import openldap from '@/assets/ico/vendor/openldap.svg?c';
|
|||
import proget from '@/assets/ico/vendor/proget.svg?c';
|
||||
import quay from '@/assets/ico/vendor/quay.svg?c';
|
||||
|
||||
const placeholder = Placeholder;
|
||||
|
||||
export const SvgIcons = {
|
||||
automode,
|
||||
darkmode,
|
||||
|
@ -96,6 +99,7 @@ export const SvgIcons = {
|
|||
memory,
|
||||
objectgroup,
|
||||
palette,
|
||||
placeholder,
|
||||
plug,
|
||||
restore,
|
||||
restorewindow,
|
||||
|
@ -124,6 +128,7 @@ export const SvgIcons = {
|
|||
google,
|
||||
googlecloud,
|
||||
kubernetes,
|
||||
helm,
|
||||
linode,
|
||||
microsoft,
|
||||
nomad,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Box, Edit, Layers, Loader, Lock, Server } from 'react-feather';
|
||||
import { Box, Edit, Layers, Lock, Server } from 'react-feather';
|
||||
|
||||
import { EnvironmentId } from '@/portainer/environments/types';
|
||||
import { Authorized } from '@/portainer/hooks/useUser';
|
||||
import Helm from '@/assets/ico/vendor/helm.svg?c';
|
||||
|
||||
import { DashboardLink } from '../items/DashboardLink';
|
||||
import { SidebarItem } from '../SidebarItem';
|
||||
|
@ -54,7 +55,7 @@ export function KubernetesSidebar({ environmentId }: Props) {
|
|||
<SidebarItem
|
||||
to="kubernetes.templates.helm"
|
||||
params={{ endpointId: environmentId }}
|
||||
icon={Loader}
|
||||
icon={Helm}
|
||||
label="Helm"
|
||||
data-cy="k8sSidebar-helm"
|
||||
/>
|
||||
|
|
Loading…
Reference in New Issue