2021-09-02 05:28:51 +00:00
import { AccessControlFormData } from '@/portainer/components/accessControlForm/porAccessControlFormModel' ;
2022-05-31 10:00:47 +00:00
import { getTemplateVariables , intersectVariables } from '@/react/portainer/custom-templates/components/utils' ;
2022-11-13 08:10:18 +00:00
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service' ;
2023-04-04 00:44:42 +00:00
import { editor , upload , git } from '@@/BoxSelector/common-options/build-methods' ;
2023-02-14 08:19:41 +00:00
import { confirmWebEditorDiscard } from '@@/modals/confirm' ;
2023-04-20 21:39:55 +00:00
import { KUBE _TEMPLATE _NAME _VALIDATION _REGEX } from '@/constants' ;
2021-09-02 05:28:51 +00:00
class KubeCreateCustomTemplateViewController {
/* @ngInject */
2023-02-14 08:19:41 +00:00
constructor ( $async , $state , Authentication , CustomTemplateService , FormValidator , Notifications , ResourceControlService ) {
Object . assign ( this , { $async , $state , Authentication , CustomTemplateService , FormValidator , Notifications , ResourceControlService } ) ;
2021-09-02 05:28:51 +00:00
2023-04-04 00:44:42 +00:00
this . methodOptions = [ editor , upload , git ] ;
2021-09-02 05:28:51 +00:00
this . templates = null ;
2022-06-16 05:32:41 +00:00
this . isTemplateVariablesEnabled = isBE ;
2021-09-02 05:28:51 +00:00
this . state = {
method : 'editor' ,
actionInProgress : false ,
formValidationError : '' ,
isEditorDirty : false ,
2022-05-31 10:00:47 +00:00
isTemplateValid : true ,
2021-09-02 05:28:51 +00:00
} ;
this . formValues = {
FileContent : '' ,
File : null ,
Title : '' ,
Description : '' ,
Note : '' ,
Logo : '' ,
AccessControlData : new AccessControlFormData ( ) ,
2022-05-31 10:00:47 +00:00
Variables : [ ] ,
2023-04-04 00:44:42 +00:00
RepositoryURL : '' ,
RepositoryURLValid : false ,
RepositoryReferenceName : 'refs/heads/main' ,
RepositoryAuthentication : false ,
RepositoryUsername : '' ,
RepositoryPassword : '' ,
ComposeFilePathInRepository : 'manifest.yml' ,
2021-09-02 05:28:51 +00:00
} ;
2023-10-22 09:19:19 +00:00
this . validationData = {
title : {
pattern : KUBE _TEMPLATE _NAME _VALIDATION _REGEX ,
error :
"This field must consist of lower-case alphanumeric characters, '.', '_' or '-', must start and end with an alphanumeric character and must be 63 characters or less (e.g. 'my-name', or 'abc-123')." ,
} ,
} ;
2021-09-02 05:28:51 +00:00
this . onChangeFile = this . onChangeFile . bind ( this ) ;
this . onChangeFileContent = this . onChangeFileContent . bind ( this ) ;
this . onChangeMethod = this . onChangeMethod . bind ( this ) ;
this . onBeforeOnload = this . onBeforeOnload . bind ( this ) ;
2022-05-31 10:00:47 +00:00
this . handleChange = this . handleChange . bind ( this ) ;
this . onVariablesChange = this . onVariablesChange . bind ( this ) ;
2023-10-22 09:19:19 +00:00
this . onChangePlatform = this . onChangePlatform . bind ( this ) ;
this . onChangeType = this . onChangeType . bind ( this ) ;
}
onChangePlatform ( value ) {
this . handleChange ( { Platform : value } ) ;
}
onChangeType ( value ) {
this . handleChange ( { Type : value } ) ;
2021-09-02 05:28:51 +00:00
}
onChangeMethod ( method ) {
this . state . method = method ;
2022-05-31 10:00:47 +00:00
this . formValues . Variables = [ ] ;
2021-09-02 05:28:51 +00:00
}
onChangeFileContent ( content ) {
2022-05-31 10:00:47 +00:00
this . handleChange ( { FileContent : content } ) ;
this . parseTemplate ( content ) ;
2021-09-02 05:28:51 +00:00
this . state . isEditorDirty = true ;
}
2022-05-31 10:00:47 +00:00
parseTemplate ( templateStr ) {
2022-06-16 05:32:41 +00:00
if ( ! this . isTemplateVariablesEnabled ) {
return ;
}
2022-05-31 10:00:47 +00:00
const variables = getTemplateVariables ( templateStr ) ;
const isValid = ! ! variables ;
this . state . isTemplateValid = isValid ;
if ( isValid ) {
this . onVariablesChange ( intersectVariables ( this . formValues . Variables , variables ) ) ;
}
}
onVariablesChange ( value ) {
this . handleChange ( { Variables : value } ) ;
}
2021-09-02 05:28:51 +00:00
onChangeFile ( file ) {
2022-05-31 10:00:47 +00:00
this . handleChange ( { File : file } ) ;
}
handleChange ( values ) {
2022-01-05 13:39:34 +00:00
return this . $async ( async ( ) => {
2022-05-31 10:00:47 +00:00
this . formValues = {
... this . formValues ,
... values ,
} ;
2022-01-05 13:39:34 +00:00
} ) ;
2021-09-02 05:28:51 +00:00
}
async createCustomTemplate ( ) {
return this . $async ( async ( ) => {
const { method } = this . state ;
if ( ! this . validateForm ( method ) ) {
return ;
}
this . state . actionInProgress = true ;
try {
2022-10-02 20:49:28 +00:00
const customTemplate = await this . createCustomTemplateByMethod ( method , this . formValues ) ;
2021-09-02 05:28:51 +00:00
const accessControlData = this . formValues . AccessControlData ;
const userDetails = this . Authentication . getUserDetails ( ) ;
const userId = userDetails . ID ;
await this . ResourceControlService . applyResourceControl ( userId , accessControlData , customTemplate . ResourceControl ) ;
2022-08-10 05:07:35 +00:00
this . Notifications . success ( 'Success' , 'Custom template successfully created' ) ;
2021-09-02 05:28:51 +00:00
this . state . isEditorDirty = false ;
this . $state . go ( 'kubernetes.templates.custom' ) ;
} catch ( err ) {
this . Notifications . error ( 'Failure' , err , 'Failed creating custom template' ) ;
} finally {
this . state . actionInProgress = false ;
}
} ) ;
}
createCustomTemplateByMethod ( method , template ) {
template . Type = 3 ;
switch ( method ) {
case 'editor' :
return this . createCustomTemplateFromFileContent ( template ) ;
case 'upload' :
return this . createCustomTemplateFromFileUpload ( template ) ;
2023-04-04 00:44:42 +00:00
case 'repository' :
return this . createCustomTemplateFromGitRepository ( template ) ;
2021-09-02 05:28:51 +00:00
}
}
createCustomTemplateFromFileContent ( template ) {
return this . CustomTemplateService . createCustomTemplateFromFileContent ( template ) ;
}
createCustomTemplateFromFileUpload ( template ) {
return this . CustomTemplateService . createCustomTemplateFromFileUpload ( template ) ;
}
2023-04-04 00:44:42 +00:00
createCustomTemplateFromGitRepository ( template ) {
return this . CustomTemplateService . createCustomTemplateFromGitRepository ( template ) ;
}
2021-09-02 05:28:51 +00:00
validateForm ( method ) {
this . state . formValidationError = '' ;
if ( method === 'editor' && this . formValues . FileContent === '' ) {
this . state . formValidationError = 'Template file content must not be empty' ;
return false ;
}
const title = this . formValues . Title ;
const isNotUnique = this . templates . some ( ( template ) => template . Title === title ) ;
if ( isNotUnique ) {
this . state . formValidationError = 'A template with the same name already exists' ;
return false ;
}
2022-05-31 10:00:47 +00:00
if ( ! this . state . isTemplateValid ) {
this . state . formValidationError = 'Template is not valid' ;
return false ;
}
2021-09-02 05:28:51 +00:00
const isAdmin = this . Authentication . isAdmin ( ) ;
const accessControlData = this . formValues . AccessControlData ;
const error = this . FormValidator . validateAccessControl ( accessControlData , isAdmin ) ;
if ( error ) {
this . state . formValidationError = error ;
return false ;
}
return true ;
}
async $onInit ( ) {
return this . $async ( async ( ) => {
const { fileContent , type } = this . $state . params ;
this . formValues . FileContent = fileContent ;
2022-05-31 10:00:47 +00:00
this . parseTemplate ( fileContent ) ;
2021-09-02 05:28:51 +00:00
if ( type ) {
this . formValues . Type = + type ;
}
try {
this . templates = await this . CustomTemplateService . customTemplates ( 3 ) ;
} catch ( err ) {
this . Notifications . error ( 'Failure loading' , err , 'Failed loading custom templates' ) ;
}
this . state . loading = false ;
window . addEventListener ( 'beforeunload' , this . onBeforeOnload ) ;
} ) ;
}
$onDestroy ( ) {
window . removeEventListener ( 'beforeunload' , this . onBeforeOnload ) ;
}
isEditorDirty ( ) {
return this . state . method === 'editor' && this . formValues . FileContent && this . state . isEditorDirty ;
}
onBeforeOnload ( event ) {
if ( this . isEditorDirty ( ) ) {
event . preventDefault ( ) ;
event . returnValue = '' ;
}
}
uiCanExit ( ) {
if ( this . isEditorDirty ( ) ) {
2023-02-14 08:19:41 +00:00
return confirmWebEditorDiscard ( ) ;
2021-09-02 05:28:51 +00:00
}
}
}
export default KubeCreateCustomTemplateViewController ;