2021-01-22 01:19:00 +08:00
< template >
2021-02-05 14:51:51 +08:00
< v -stepper v-model ="step" >
< v -stepper -header >
< v -stepper -step step = "1" : complete = "step > 1" > { { $t ( 'project.new.step1.title' ) } } < / v - s t e p p e r - s t e p >
< v -divider / >
2021-02-06 03:50:18 +08:00
< v -stepper -step step = "2" : complete = "step > 2 && forms.step2" : rules = "[() => noBasicSettingsError]"
2021-02-05 14:51:51 +08:00
> { { $t ( 'project.new.step2.title' ) } } < small v-show ="!noBasicSettingsError" > Missing Information < / small > < / v -stepper -step
>
< v -divider / >
< v -stepper -step step = "3" : complete = "step > 3"
> { { $t ( 'project.new.step3.title' ) } } < small > { { $t ( 'project.new.step3.optional' ) } } < / small > < / v - s t e p p e r - s t e p
>
< v -divider / >
< v -stepper -step step = "4" : complete = "step > 4"
> { { $t ( 'project.new.step4.title' ) } } < small > { { $t ( 'project.new.step4.optional' ) } } < / small > < / v - s t e p p e r - s t e p
>
< v -divider / >
2021-02-06 03:50:18 +08:00
< v -stepper -step step = "5" :complete ="!projectLoading" > { { $t ( 'project.new.step5.title' ) } } < / v - s t e p p e r - s t e p >
2021-02-05 14:51:51 +08:00
< / v - s t e p p e r - h e a d e r >
< v -stepper -items >
< StepperStepContent :step ="1" @back ="$router.push('/')" @ continue = "step = 2" >
< v -card class = "mb-12 pa-1" min -height = " 200px " >
< v -card -title v-if ="$vuetify.breakpoint.smAndDown" >
{ { $t ( 'project.new.step1.title' ) } }
< / v - c a r d - t i t l e >
2021-02-11 19:48:52 +08:00
<!-- eslint - disable - next - line vue / no - v - html -- >
2021-02-05 14:51:51 +08:00
< v -card -text v-html ="$t('project.new.step1.text')" > < / v -card -text >
< / v - c a r d >
< / StepperStepContent >
< StepperStepContent :step ="2" :allow-continue ="noBasicSettingsError" @ back = "step = 1" @ continue = "step = 3" >
< v -card max -width = " 800 " class = "mx-auto" >
< v -card -title v-if ="$vuetify.breakpoint.smAndDown" >
{ { $t ( 'project.new.step2.title' ) } }
< / v - c a r d - t i t l e >
2021-02-06 03:50:18 +08:00
< v -form v-model ="forms.step2" >
2021-02-05 14:51:51 +08:00
< v -container >
< v -row justify = "space-around" >
< v -col cols = "12" md = "6" >
< v -select
v - model = "form.ownerId"
: items = "projectOwners"
dense
filled
item - text = "name"
item - value = "userId"
: label = "$t('project.new.step2.userselect')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.require($t('project.new.step2.userselect'))]"
2021-02-05 14:51:51 +08:00
: append - icon = "createAsIcon"
/ >
< / v - c o l >
< v -col cols = "12" md = "6" >
2021-02-11 19:48:52 +08:00
<!-- todo custom rule to check if a name exist already -- >
2021-02-05 14:51:51 +08:00
< v -text -field
v - model . trim = "form.name"
autofocus
dense
filled
2021-02-12 13:44:49 +08:00
: error - messages = "nameErrors"
2021-02-05 14:51:51 +08:00
: label = "$t('project.new.step2.projectname')"
2021-03-20 09:56:08 +08:00
: rules = "[$util.$vc.require($t('project.new.step2.projectname'))]"
2021-02-05 14:51:51 +08:00
append - icon = "mdi-form-textbox"
/ >
< / v - c o l >
< v -col cols = "12" md = "8" >
< v -text -field
v - model . trim = "form.description"
dense
filled
clearable
: label = "$t('project.new.step2.projectsummary')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.require($t('project.new.step2.projectsummary')), $util.$vc.maxLength(validations.project.desc.max)]"
2021-02-05 14:51:51 +08:00
append - icon = "mdi-card-text"
/ >
< / v - c o l >
< v -col cols = "12" md = "4" >
< v -select
v - model = "form.category"
2021-03-18 13:25:52 +08:00
: prepend - inner - icon = "categoryIcon"
2021-02-05 14:51:51 +08:00
: items = "$store.getters.visibleCategories"
dense
filled
: label = "$t('project.new.step2.projectcategory')"
item - text = "title"
item - value = "apiName"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.require($t('project.new.step2.projectcategory'))]"
2021-02-05 14:51:51 +08:00
/ >
< / v - c o l >
< / v - r o w >
< / v - c o n t a i n e r >
< / v - f o r m >
< / v - c a r d >
< / StepperStepContent >
< StepperStepContent :step ="3" @ back = "step = 2" @ continue = "step = 4" >
< v -card max -width = " 800 " class = "mx-auto" >
< v -card -title v-if ="$vuetify.breakpoint.smAndDown" >
{ { $t ( 'project.new.step3.title' ) } }
< / v - c a r d - t i t l e >
2021-02-06 03:50:18 +08:00
< v -container >
< div class = "text-h6 pt-1" >
< v -icon color = "info" large style = "transform: rotate(-45deg)" class = "mb-1" > mdi - link < / v - i c o n >
{ { $t ( 'project.new.step3.links' ) } }
< / div >
< v -divider class = "mb-2" / >
< v -row >
< v -col cols = "12" >
< v -text -field
2021-03-18 14:10:12 +08:00
v - model . trim = "form.settings.homepage"
2021-02-06 03:50:18 +08:00
dense
hide - details
filled
: label = "$t('project.new.step3.homepage')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.url]"
2021-02-06 03:50:18 +08:00
append - icon = "mdi-home-search"
/ >
< / v - c o l >
< v -col cols = "12" >
< v -text -field
2021-03-18 14:10:12 +08:00
v - model . trim = "form.settings.issues"
2021-02-06 03:50:18 +08:00
dense
hide - details
filled
: label = "$t('project.new.step3.issues')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.url]"
2021-02-06 03:50:18 +08:00
append - icon = "mdi-bug"
/ >
< / v - c o l >
< v -col cols = "12" >
< v -text -field
2021-03-18 14:10:12 +08:00
v - model . trim = "form.settings.source"
2021-02-06 03:50:18 +08:00
dense
hide - details
filled
: label = "$t('project.new.step3.source')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.url]"
2021-02-06 03:50:18 +08:00
append - icon = "mdi-source-branch"
/ >
< / v - c o l >
< v -col cols = "12" >
< v -text -field
2021-03-18 14:10:12 +08:00
v - model . trim = "form.settings.support"
2021-02-06 03:50:18 +08:00
dense
hide - details
filled
: label = "$t('project.new.step3.support')"
2021-03-20 08:00:38 +08:00
: rules = "[$util.$vc.url]"
2021-02-06 03:50:18 +08:00
append - icon = "mdi-face-agent"
/ >
< / v - c o l >
< / v - r o w >
< div class = "text-h6 pt-5" >
< v -icon color = "info" large class = "mb-1" > mdi - license < / v - i c o n >
{ { $t ( 'project.new.step3.licence' ) } }
< / div >
< v -divider class = "mb-2" / >
< v -row >
< v -col cols = "12" : md = "isCustomLicense ? 4 : 6" >
< v -select
2021-03-18 14:10:12 +08:00
v - model = "form.settings.license.type"
2021-02-06 03:50:18 +08:00
dense
hide - details
filled
clearable
: items = "licences"
: label = "$t('project.new.step3.type')"
/ >
< / v - c o l >
< v -col v-if ="isCustomLicense" cols="12" md="8" >
2021-03-18 14:32:23 +08:00
< v -text -field v -model .trim = " form.settings.license.name " dense hide -details filled :label ="$t('project.new.step3.customName')" / >
2021-02-06 03:50:18 +08:00
< / v - c o l >
< v -col cols = "12" : md = "isCustomLicense ? 12 : 6" >
2021-03-20 08:00:38 +08:00
< v -text -field
v - model . trim = "form.settings.license.url"
dense
hide - details
filled
: label = "$t('project.new.step3.url')"
: rules = "[$util.$vc.url]"
/ >
2021-02-06 03:50:18 +08:00
< / v - c o l >
< / v - r o w >
< div class = "text-h6 pt-5" >
< v -icon color = "info" large class = "mb-1" > mdi - cloud - search < / v - i c o n >
{ { $t ( 'project.new.step3.seo' ) } }
< / div >
< v -divider class = "mb-2" / >
< v -row >
< v -col cols = "12" >
< v -combobox
2021-03-18 14:10:12 +08:00
v - model = "form.settings.keywords"
2021-02-06 03:50:18 +08:00
small - chips
deletable - chips
multiple
dense
hide - details
filled
2021-03-20 08:00:38 +08:00
clearable
2021-02-06 03:50:18 +08:00
: delimiters = "[' ', ',', '.']"
: label = "$t('project.new.step3.keywords')"
append - icon = "mdi-file-word-box"
/ >
< / v - c o l >
< / v - r o w >
< / v - c o n t a i n e r >
2021-02-05 14:51:51 +08:00
< / v - c a r d >
< / StepperStepContent >
2021-02-06 03:50:18 +08:00
< StepperStepContent
: step = "4"
@ back = "step = 3"
@ continue = "
step = 5 ;
createProject ( ) ;
"
>
2021-02-05 14:51:51 +08:00
< v -tabs v -model = " spigotConvertTab " fixed -tabs >
< v -tab v-text ="$t('project.new.step4.convert')" > < / v-tab >
< v -tab v-text ="$t('project.new.step4.preview')" > < / v-tab >
< v -tab v-text ="$t('project.new.step4.tutorial')" > < / v-tab >
< / v - t a b s >
< v -tabs -items v-model ="spigotConvertTab" >
<!-- todo spigot bbcode converter thingy -- >
< v -tab -item > 1 < / v - t a b - i t e m >
< v -tab -item > 2 < / v - t a b - i t e m >
< v -tab -item > 3 < / v - t a b - i t e m >
< / v - t a b s - i t e m s >
< / StepperStepContent >
< StepperStepContent :step ="5" hide -buttons >
< v -card >
< v -card -text class = "text-center" >
2021-02-06 03:50:18 +08:00
< v -progress -circular v-if ="projectLoading" indeterminate color="red" size="50" > < / v -progress -circular >
< div v-if ="!projectError" class="text-h5 mt-2" > {{ $ t ( ' project.new.step5.text ' ) }} < / div >
< template v-else >
2021-02-13 14:36:53 +08:00
< div class = "text-h5 mt-2" > { { $t ( 'project.new.error.create' ) } } < / div >
< v -btn @click ="retry" > Retry < / v-btn >
2021-02-06 03:50:18 +08:00
< / template >
2021-02-05 14:51:51 +08:00
< / v - c a r d - t e x t >
< / v - c a r d >
< / StepperStepContent >
< / v - s t e p p e r - i t e m s >
2021-01-31 01:27:36 +08:00
< / v - s t e p p e r >
2021-01-22 01:19:00 +08:00
< / template >
< script lang = "ts" >
2021-03-21 10:06:09 +08:00
import { Component , Watch } from 'nuxt-property-decorator' ;
2021-02-05 14:51:51 +08:00
import { Context } from '@nuxt/types' ;
2021-03-18 14:10:12 +08:00
import { ProjectOwner , ProjectSettingsForm } from 'hangar-internal' ;
2021-02-12 13:44:49 +08:00
import { AxiosError } from 'axios' ;
2021-02-13 14:36:53 +08:00
import { TranslateResult } from 'vue-i18n' ;
2021-02-05 14:51:51 +08:00
import StepperStepContent from '~/components/steppers/StepperStepContent.vue' ;
import { RootState } from '~/store' ;
import { ProjectCategory } from '~/types/enums' ;
2021-03-21 10:06:09 +08:00
import { HangarComponent } from '~/components/mixins' ;
2021-02-05 14:51:51 +08:00
2021-03-18 14:10:12 +08:00
interface NewProjectForm extends ProjectSettingsForm {
2021-02-05 14:51:51 +08:00
ownerId : ProjectOwner [ 'userId' ] ;
name : string ;
pageContent : string | null ;
}
2021-01-31 10:00:11 +08:00
2021-01-31 01:27:36 +08:00
@ Component ( {
2021-02-05 14:51:51 +08:00
components : {
StepperStepContent ,
} ,
2021-02-04 17:34:24 +08:00
head : {
title : 'New Project' ,
} ,
2021-01-31 01:27:36 +08:00
} )
2021-03-21 10:06:09 +08:00
export default class NewProjectPage extends HangarComponent {
2021-01-31 01:27:36 +08:00
step = 1 ;
spigotConvertTab = 0 ;
2021-02-06 03:50:18 +08:00
projectLoading = true ;
projectError = false ;
projectOwners ! : ProjectOwner [ ] ;
error = null as string | null ;
2021-03-18 14:10:12 +08:00
form : NewProjectForm = {
2021-02-05 14:51:51 +08:00
category : ProjectCategory . ADMIN _TOOLS ,
2021-03-18 14:10:12 +08:00
settings : ( {
license : { } as ProjectSettingsForm [ 'settings' ] [ 'license' ] ,
keywords : [ ] ,
} as unknown ) as ProjectSettingsForm [ 'settings' ] ,
} as NewProjectForm ;
2021-02-05 14:51:51 +08:00
2021-02-13 14:36:53 +08:00
nameErrors : TranslateResult [ ] = [ ] ;
2021-02-12 13:44:49 +08:00
2021-02-05 14:51:51 +08:00
forms = {
2021-02-06 03:50:18 +08:00
step2 : false ,
2021-02-05 14:51:51 +08:00
} ;
get categoryIcon ( ) {
return ( this . $store . state as RootState ) . projectCategories . get ( this . form . category ) ? . icon ;
}
2021-01-31 01:27:36 +08:00
2021-02-05 14:51:51 +08:00
get createAsIcon ( ) {
return this . projectOwners . find ( ( po ) => po . userId === this . form . ownerId ) ? . isOrganization ? 'mdi-account-multiple' : 'mdi-account' ;
2021-01-31 01:27:36 +08:00
}
2021-02-05 14:51:51 +08:00
get isCustomLicense ( ) {
2021-03-18 14:10:12 +08:00
return this . form . settings . license . type === '(custom)' ;
2021-01-31 01:27:36 +08:00
}
2021-01-22 01:19:00 +08:00
2021-02-05 14:51:51 +08:00
get noBasicSettingsError ( ) {
2021-02-06 03:50:18 +08:00
return this . step !== 2 || this . forms . step2 ;
2021-02-05 14:51:51 +08:00
}
// TODO do we want to get those from the server? Jake: I think so, it'd be nice to admins to be able to configure default licenses, but not needed for MVP
2021-01-31 01:27:36 +08:00
get licences ( ) {
2021-02-05 14:51:51 +08:00
return [ 'MIT' , 'Apache 2.0' , 'GPL' , 'LGPL' , '(custom)' ] ;
2021-01-31 01:27:36 +08:00
}
2021-01-31 02:50:12 +08:00
2021-02-05 14:51:51 +08:00
async asyncData ( { $api } : Context ) {
return {
projectOwners : await $api . requestInternal < ProjectOwner [ ] > ( 'projects/possibleOwners' ) ,
} ;
}
created ( ) {
this . form . ownerId = this . projectOwners . find ( ( po ) => ! po . isOrganization ) ? . userId ! ;
}
2021-01-22 01:19:00 +08:00
2021-02-06 03:50:18 +08:00
createProject ( ) {
console . log ( this . form ) ;
this . $api
2021-02-06 15:45:13 +08:00
. requestInternal < string > ( 'projects/create' , true , 'post' , this . form )
. then ( ( url ) => {
this . $router . push ( url ) ;
2021-02-06 03:50:18 +08:00
} )
. catch ( ( err ) => {
this . projectError = true ;
2021-02-13 14:36:53 +08:00
this . $util . handleRequestError ( err , 'project.new.error.create' ) ;
2021-02-06 03:50:18 +08:00
} )
. finally ( ( ) => {
this . projectLoading = false ;
} ) ;
}
2021-02-12 13:44:49 +08:00
2021-02-13 14:36:53 +08:00
retry ( ) {
this . step = 1 ;
this . projectLoading = true ;
this . projectError = false ;
}
2021-02-12 13:44:49 +08:00
// This is very useful. Prob should have a generalization of this that works elsewhere. I didn't make it a rule because it relies on other input (the ownerId)
@ Watch ( 'form.name' )
onProjectNameChange ( val : string ) {
if ( ! val ) {
this . nameErrors = [ ] ;
return ;
}
this . $api
. requestInternal ( 'projects/validateName' , false , 'get' , {
userId : this . form . ownerId ,
value : val ,
} )
. then ( ( ) => {
this . nameErrors = [ ] ;
} )
. catch ( ( err : AxiosError ) => {
this . nameErrors = [ ] ;
if ( ! err . response ? . data . isHangarApiException ) {
return this . $util . handleRequestError ( err ) ;
}
2021-02-13 14:36:53 +08:00
this . nameErrors . push ( this . $t ( err . response . data . message ) ) ;
2021-02-12 13:44:49 +08:00
} ) ;
}
2021-01-31 01:27:36 +08:00
}
2021-02-05 14:51:51 +08:00
< / script >