summaryrefslogblamecommitdiffstats
path: root/webapp/src/components/IpxeBuilderModuleConfig.vue
blob: 6454d41f8520d55a637fe942ca918fe6bc371419 (plain) (tree)
1
2
3
4
5
6
7
8
9


         
                                                               
                   
                                        
                              
                                
                                                         
                                        


                                                   
                 
                           
                                                   
                   








                                                                            
                              
                                 
                                                                   
                           
                                                              
                                               








                                                                        





          
                                               
 








                                                                                                                             
             
       
 
                                                                
                                                                                           
                                              
                                                                                                                                          
                 
             






                                                                                                           
                               
                                                                                                                                     
                                                                                                                                          
                                                                                                                                      
          
                               
                                                                       















                                                                                                                
                                                         














                                                                                                                     
                                                         














                                                                                                                 
                                                         




















                                                                                                                 
                                  













                                
              

                            





                                                               

                                       

                                                                

                                            

                                                                          

                                        

                                                                  

                                        


















                                                                                                           

                                                                                                                                



                                                                            

                                                                                                                                
        




                                                                                                                           

                          
                                                   
                                                                                                            


                            
















                                                                                
                                                                                



                                          
                                                                                            




                                                         









                                                                                                    


              
                          
                                                  
                                                                    
     





                                                                   













                                        
        
<i18n>
{
  "en": {
    "alreadyBuiling": "The iPXE building process not finished",
    "bios": "BIOS",
    "buildingIpxe": "Building iPXE ...",
    "buildIpxe": "Build iPXE",
    "cancelIpxe": "Cancel iPXE",
    "certificateSaved": "Certificate saved successfully",
    "cleaningIpxe": "Cleaning iPXE ...",
    "cleanIpxe": "Clean iPXE",
    "console": "console.h",
    "consoleSaved": "console.h saved successfully",
    "efi": "EFI",
    "general": "general.h",
    "generalSaved": "general.h saved successfully",
    "ipxe": "iPXE",
    "script": "Embedded script (EMBED=)",
    "scriptSaved": "Embedded script saved successfully",
    "scrollDown": "Go to the bottom",
    "trust": "Embedded certificate (TRUST=)"
  },
  "de": {
    "alreadyBuiling": "Der iPXE build-Prozess ist noch nicht abgeschlossen",
    "bios": "BIOS",
    "buildingIpxe": "iPXE wird gebaut ...",
    "buildIpxe": "iPXE bauen",
    "cancelIpxe": "iPXE stoppen",
    "certificateSaved": "Zertifikat wurde erfolgreich gespeichert",
    "console": "console.h",
    "consoleSaved": "console.h wurde erfolgreich gespeichert",
    "cleaningIpxe": "iPXE wird aufgeräumt ..",
    "cleanIpxe": "iPXE aufräumen",
    "efi": "EFI",
    "general": "general.h",
    "generalSaved": "general.h wurde erfolgreich gespeichert",
    "ipxe": "iPXE",
    "script": "Eingebettetes Skript (EMBED=)",
    "scriptSaved": "Eingebettetes Skript wurde erfolgreich gespeichert",
    "scrollDown": "Gehe nach unten",
    "trust": "Eingebettetes Zertifikat (TRUST=)"
  }
}
</i18n>

<template>
  <div>
    <v-subheader>{{ $t('ipxe') }}</v-subheader>

    <!--
    <v-card v-on:wheel="manualScroll">
      <div>
        <RecycleScroller :items="log" ref="log" :item-size="21" style="height: 588px;">
          <div slot-scope="{ item }" style="height: 21px;">
            <pre :class="item.status + '--text'" style="margin-bottom: 0px"><span>{{ item.date }} {{ item.msg }}</span></pre>
          </div>
        </RecycleScroller>
      </div>
    </v-card>
    -->

    <!-- Recycle Scroller or not?! One of them ^v has to go! -->
    <v-card class="terminal" ref="log" v-on:wheel="manualScroll" style="padding-left: 0px">
      <template v-for="(entry, index) in log">
        <pre :class="entry.status + '--text'" style="margin-bottom: 0px;" :key="index"><span>{{ entry.date }} {{ entry.msg }}</span></pre>
      </template>
    </v-card>

    <div class="scroll-overlay non-selectable" v-if="!autoscroll">
      <div @click="toTheBottom" style="cursor: pointer; height: 100%; display: flex; align-items: center;">
        <v-icon style="margin-right: 10px">vertical_align_bottom</v-icon><pre>{{ $t('scrollDown') }}</pre>
      </div>
    </div>

    <div class="text-xs-right">
      <v-btn flat color="error" @click="cleanIpxe" :disabled=disableButtons><v-icon left>delete</v-icon>{{ $t('cleanIpxe') }}</v-btn>
      <v-btn flat color="warning" @click="cancelIpxe" :disabled=!disableButtons><v-icon left>cancel</v-icon>{{ $t('cancelIpxe') }}</v-btn>
      <v-btn flat color="primary" @click="buildIpxe" :disabled=disableButtons><v-icon left>gavel</v-icon>{{ $t('buildIpxe') }}</v-btn>
    </div>
    <v-subheader></v-subheader>
    <v-expansion-panel v-model="scriptExpanded" class="non-selectable">
       <v-expansion-panel-content>
        <div slot="header">{{ $t('script') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="script" v-model="script"></codemirror>
        </v-card>
        <!--<v-divider></v-divider>-->
        <div class="text-xs-right">
          <v-btn flat color="error" @click="undo('script')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
          <v-btn flat color="success" @click="redo('script')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
          <v-btn color="primary" @click="save('script')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
        </div>
      </v-expansion-panel-content>
    </v-expansion-panel>

    <v-subheader></v-subheader>
    <v-expansion-panel v-model="certificateExpanded">
       <v-expansion-panel-content class="non-selectable">
        <div slot="header">{{ $t('trust') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="certificate" v-model="certificate"></codemirror>
        </v-card>
        <!--<v-divider></v-divider>-->
        <div class="text-xs-right">
          <v-btn flat color="error" @click="undo('certificate')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
          <v-btn flat color="success" @click="redo('certificate')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
          <v-btn color="primary" @click="save('certificate')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
        </div>
      </v-expansion-panel-content>
    </v-expansion-panel>

    <v-subheader></v-subheader>
    <v-expansion-panel v-model="generalExpanded">
       <v-expansion-panel-content class="non-selectable">
        <div slot="header">{{ $t('general') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="general" v-model="general"></codemirror>
        </v-card>
        <!--<v-divider></v-divider>-->
        <div class="text-xs-right">
          <v-btn flat color="error" @click="undo('general')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
          <v-btn flat color="success" @click="redo('general')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
          <v-btn color="primary" @click="save('general')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
        </div>
      </v-expansion-panel-content>
    </v-expansion-panel>

    <v-subheader></v-subheader>
    <v-expansion-panel v-model="consoleExpanded">
       <v-expansion-panel-content class="non-selectable">
        <div slot="header">{{ $t('console') }}</div>
        <v-card>
          <codemirror class="script-editor" ref="console" v-model="console"></codemirror>
        </v-card>
        <!--<v-divider></v-divider>-->
        <div class="text-xs-right">
          <v-btn flat color="error" @click="undo('console')"><v-icon left>undo</v-icon>{{ $t('undo') }}</v-btn>
          <v-btn flat color="success" @click="redo('console')"><v-icon left>redo</v-icon>{{ $t('redo') }}</v-btn>
          <v-btn color="primary" @click="save('console')"><v-icon left>save</v-icon>{{ $t('save') }}</v-btn>
        </div>
      </v-expansion-panel-content>
    </v-expansion-panel>

  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import axios from 'axios'

export default {
  name: 'IpxeBuilderModuleConfig',
  props: ['ipxeVersion'],
  components: {
  },
  data () {
    return {
      tabs: 0,
      script: '',
      certificate: '',
      general: '',
      console: '',
      scriptExpanded: null,
      certificateExpanded: null,
      generalExpanded: null,
      consoleExpanded: null,
      log: [],
      disableButtons: false,
      autoscroll: true
    }
  },
  computed: {
    ...mapGetters(['tabsDark', 'tabsColor', 'tabsSliderColor'])
  },
  watch: {
    scriptExpanded: async function () {
      await this.$nextTick()
      if (this.scriptExpanded === 0) this.$refs.script.refresh()
    },
    certificateExpanded: async function () {
      await this.$nextTick()
      if (this.certificateExpanded === 0) this.$refs.certificate.refresh()
    },
    generalExpanded: async function () {
      await this.$nextTick()
      if (this.generalExpanded === 0) this.$refs.general.refresh()
    },
    consoleExpanded: async function () {
      await this.$nextTick()
      if (this.consoleExpanded === 0) this.$refs.console.refresh()
    }
  },
  methods: {
    save (apiPath) {
      axios.put('/api/ipxe/' + this.ipxeVersion + '/' + apiPath, { data: this[apiPath] }).then(result => {
        const saveMsg = apiPath + 'Saved'
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'success', text: this.$tc(saveMsg) })
        else this.$snackbar({ color: 'error', text: result.data.error })
      })
    },
    undo (element) {
      this.$refs[element].codemirror.undo()
    },
    redo (element) {
      this.$refs[element].codemirror.redo()
    },
    buildIpxe () {
      axios.get('/api/ipxe/' + this.ipxeVersion + '/build').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('buildingIpxe') })
        else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
      })
    },
    cleanIpxe () {
      axios.get('/api/ipxe/' + this.ipxeVersion + '/clean').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') })
        else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
      })
    },
    cancelIpxe () {
      axios.get('/api/ipxe/' + this.ipxeVersion + '/cancel').then(result => {
        if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') }) // TODO:
      })
    },
    manualScroll (event) {
      if (event.deltaY < 0) this.autoscroll = false
      else if (this.$refs.log.$el.scrollTop + 800 >= this.$refs.log.$el.scrollHeight) this.autoscroll = true
    },
    toTheBottom () {
      this.autoscroll = true
    }
  },
  created () {
    // Load the data.
    axios.get('/api/ipxe/' + this.ipxeVersion + '/script').then(result => {
      this.script = result.data
    })
    axios.get('/api/ipxe/' + this.ipxeVersion + '/certificate').then(result => {
      this.certificate = result.data
    })
    axios.get('/api/ipxe/' + this.ipxeVersion + '/general').then(result => {
      this.general = result.data
    })
    axios.get('/api/ipxe/' + this.ipxeVersion + '/console').then(result => {
      this.console = result.data
    })

    axios.get('/api/ipxe/' + this.ipxeVersion + '/log?max=500').then(result => {
      var lines = result.data.split('\n')
      for (var line in lines) {
        if (lines[line] === '') continue
        var attr = lines[line].split('\t')
        this.log.push({ id: this.log.length, date: attr[0], status: attr[1], msg: attr[2] })
      }
    })

    // Socket io event listeners
    this.$socket.on(this.ipxeVersion + ' log', entry => {
      this.log.push({ id: this.log.length, msg: entry.msg, status: entry.status, date: entry.date })
    })

    // Disable the buttons if a building process is running.
    axios.get('/api/ipxe/' + this.ipxeVersion + '/status').then(result => {
      this.disableButtons = result.data.data
    })

    this.$socket.on(this.ipxeVersion + ' inProgress', inProgress => {
      this.disableButtons = inProgress
    })
  },
  updated () {
    if (this.autoscroll) {
      // Use this instead for the virtual scroller
      this.$refs.log.$el.scrollTop = this.$refs.log.$el.scrollHeight
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .scroll-overlay {
    position: absolute;
    margin-top: -35px;
    width: 100%;
    display: flex;
    justify-content: center;
    background-color: rgba(0, 0, 0, .5);
    height: 35px;
  }
  .terminal {
    padding: 12px 24px 12px 24px;
    height: 588px;
    overflow: auto;
  }
</style>