Merge branch 'feature/vuejs-serverlist' into feature/vue-serverview
This commit is contained in:
		
						commit
						c58ef1f8a8
					
				| @ -1,7 +1,12 @@ | ||||
| <template> | ||||
|     <div v-if="notifications.length > 0"> | ||||
|         <transition-group tag="div" class="mb-2" name="fade"> | ||||
|             <div :class="item.class" class="lg:inline-flex mb-2" role="alert" :key="index" v-for="(item, index) in notifications"> | ||||
|     <div v-if="notifications.length > 0" :class="this.container"> | ||||
|         <transition-group tag="div" name="fade"> | ||||
|             <div class="lg:inline-flex" role="alert" v-for="(item, index) in notifications" | ||||
|                 :key="index" | ||||
|                 :class="[item.class, { | ||||
|                     'mb-2': index < notifications.length - 1 | ||||
|                 }]" | ||||
|             > | ||||
|                 <span class="title" v-html="item.title" v-if="item.title.length > 0"></span> | ||||
|                 <span class="message" v-html="item.message"></span> | ||||
|             </div> | ||||
| @ -13,6 +18,10 @@ | ||||
|     export default { | ||||
|         name: 'flash', | ||||
|         props: { | ||||
|             container: { | ||||
|                 type: String, | ||||
|                 default: '', | ||||
|             }, | ||||
|             timeout: { | ||||
|                 type: Number, | ||||
|                 default: 0, | ||||
|  | ||||
| @ -1,13 +1,21 @@ | ||||
| <template> | ||||
|     <div> | ||||
|         <flash container="mt-4"/> | ||||
|         <div class="server-search animate fadein"> | ||||
|             <input type="text" placeholder="search for servers..." | ||||
|             <input type="text" | ||||
|                    :placeholder="$t('dashboard.index.search')" | ||||
|                    @input="onChange" | ||||
|                    v-model="search" | ||||
|                    ref="search" | ||||
|             /> | ||||
|         </div> | ||||
|         <transition-group class="w-full m-auto mt-4 animate fadein sm:flex flex-wrap content-start"><div class="server-box" :key="index" v-for="(server, index) in servers.models"> | ||||
|         <div v-if="this.loading" class="my-4 animate fadein"> | ||||
|             <div class="text-center h-16"> | ||||
|                 <span class="spinner spinner-xl"></span> | ||||
|             </div> | ||||
|         </div> | ||||
|         <transition-group class="w-full m-auto mt-4 animate fadein sm:flex flex-wrap content-start" v-else> | ||||
|             <div class="server-box animate fadein" :key="index" v-for="(server, index) in servers.models"> | ||||
|                 <router-link :to="{ name: 'server', params: { id: server.identifier }}" class="content"> | ||||
|                     <div class="float-right"> | ||||
|                         <div class="indicator"></div> | ||||
| @ -19,10 +27,10 @@ | ||||
|                     </div> | ||||
|                     <div class="mb-0 flex"> | ||||
|                         <div class="usage"> | ||||
|                             <div class="indicator-title">CPU</div> | ||||
|                             <div class="indicator-title">{{ $t('dashboard.index.cpu_title') }}</div> | ||||
|                         </div> | ||||
|                         <div class="mb-4"> | ||||
|                             <div class="text-black font-bold text-xl">{{ server.name }}</div> | ||||
|                         <div class="usage"> | ||||
|                             <div class="indicator-title">{{ $t('dashboard.index.memory_title') }}</div> | ||||
|                         </div> | ||||
|                         <div class="mb-0 flex"> | ||||
|                             <div class="usage"> | ||||
| @ -58,11 +66,14 @@ | ||||
| <script> | ||||
|     import { ServerCollection } from '../../models/server'; | ||||
|     import _ from 'lodash'; | ||||
|     import Flash from '../Flash'; | ||||
| 
 | ||||
|     export default { | ||||
|         name: 'dashboard', | ||||
|         components: { Flash }, | ||||
|         data: function () { | ||||
|             return { | ||||
|                 loading: true, | ||||
|                 search: '', | ||||
|                 servers: new ServerCollection, | ||||
|             } | ||||
| @ -79,17 +90,34 @@ | ||||
|              * @param {string} query | ||||
|              */ | ||||
|             loadServers: function (query = '') { | ||||
|                 this.loading = true; | ||||
|                 window.axios.get(this.route('api.client.index'), { | ||||
|                     params: { query }, | ||||
|                 }) | ||||
|                     .finally(() => { | ||||
|                         this.clearFlashes(); | ||||
|                     }) | ||||
|                     .then(response => { | ||||
|                         this.servers = new ServerCollection; | ||||
|                         response.data.data.forEach(obj => { | ||||
|                             this.servers.add(obj.attributes); | ||||
|                         }); | ||||
| 
 | ||||
|                         if (this.servers.models.length === 0) { | ||||
|                             this.info(this.$t('dashboard.index.no_matches')); | ||||
|                         } | ||||
|                     }) | ||||
|                     .catch(error => { | ||||
|                         console.error(error); | ||||
|                     .catch(err => { | ||||
|                         console.error(err); | ||||
|                         const response = err.response; | ||||
|                         if (response.data && _.isObject(response.data.errors)) { | ||||
|                             response.data.errors.forEach(function (error) { | ||||
|                                 this.error(error.detail); | ||||
|                             }); | ||||
|                         } | ||||
|                     }) | ||||
|                     .finally(() => { | ||||
|                         this.loading = false; | ||||
|                     }); | ||||
|             }, | ||||
| 
 | ||||
|  | ||||
| @ -1,33 +1,48 @@ | ||||
| import { Collection, Model } from 'vue-mc'; | ||||
| import JwtDecode from 'jwt-decode'; | ||||
| 
 | ||||
| const User = function () { | ||||
|     this.id = 0; | ||||
|     this.admin = false; | ||||
|     this.email = ''; | ||||
| }; | ||||
| export class User extends Model { | ||||
|     static defaults() { | ||||
|         return { | ||||
|             id: null, | ||||
|             uuid: '', | ||||
|             username: '', | ||||
|             email: '', | ||||
|             name_first: '', | ||||
|             name_last: '', | ||||
|             language: 'en', | ||||
|             root_admin: false, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| /** | ||||
|  * Return a new instance of the user model using a JWT. | ||||
|  * | ||||
|  * @param {string} token | ||||
|  * @returns {User} | ||||
|  */ | ||||
| User.prototype.fromJwt = function (token) { | ||||
|     return this.newModel(JwtDecode(token)); | ||||
| }; | ||||
|     static mutations() { | ||||
|         return { | ||||
|             id: Number, | ||||
|             uuid: String, | ||||
|             username: String, | ||||
|             email: String, | ||||
|             name_first: String, | ||||
|             name_last: String, | ||||
|             language: String, | ||||
|             root_admin: Boolean, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| /** | ||||
|  * Return an instance of this user model with the properties set on it. | ||||
|  * | ||||
|  * @param {object} obj | ||||
|  * @returns {User} | ||||
|  */ | ||||
| User.prototype.newModel = function (obj) { | ||||
|     this.id = obj.id; | ||||
|     this.admin = obj.admin; | ||||
|     this.email = obj.email; | ||||
|     static fromJWT(token) { | ||||
|         return new User(JwtDecode(token).user || {}); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     return this; | ||||
| }; | ||||
| export class UserCollection extends Collection { | ||||
|     static model() { | ||||
|         return User; | ||||
|     } | ||||
| 
 | ||||
| export default User; | ||||
|     get todo() { | ||||
|         return this.sum('done'); | ||||
|     } | ||||
| 
 | ||||
|     get done() { | ||||
|         return this.todo === 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import User from './models/user'; | ||||
| import { User } from './models/user'; | ||||
| 
 | ||||
| export const storeData = { | ||||
|     state: { | ||||
| @ -13,15 +13,25 @@ export const storeData = { | ||||
|         }, | ||||
|     }, | ||||
|     getters: { | ||||
|         user: function (state) { | ||||
|         getCurrentUser: function (state) { | ||||
|             if (!(state.user instanceof User)) { | ||||
|                 state.user = User.fromJWT(localStorage.getItem('token')); | ||||
|             } | ||||
| 
 | ||||
|             return state.user; | ||||
|         }, | ||||
|     }, | ||||
|     mutations: { | ||||
|         /** | ||||
|          * Log in a user and store them in vuex using the local storage token. | ||||
|          * | ||||
|          * @param state | ||||
|          */ | ||||
|         login: function (state) { | ||||
|             state.user = new User().fromJwt(localStorage.getItem('token')); | ||||
|             state.user = User.fromJWT(localStorage.getItem('token')); | ||||
|         }, | ||||
|         logout: function (state) { | ||||
|             console.log('logout'); | ||||
|             state.user = null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -4,18 +4,21 @@ | ||||
|   position: relative; | ||||
| 
 | ||||
|   &:after { | ||||
|     @apply .border-2 .border-grey-light .absolute .block; | ||||
|     animation: spinners--spin 500ms infinite linear; | ||||
|     border-radius: 9999px; | ||||
|     @apply .border-2 .border-grey-light; | ||||
|     border-top-color: transparent !important; | ||||
|     border-right-color: transparent !important; | ||||
|     content: ''; | ||||
|     display: block; | ||||
|     width: 1em; | ||||
|     height: 1em; | ||||
|     left: calc(50% - (1em / 2)); | ||||
|     top: calc(50% - (1em / 2)); | ||||
|     position: absolute !important; | ||||
|   } | ||||
| 
 | ||||
|   &.spinner-xl:after { | ||||
|     @apply .h-16 .w-16; | ||||
|     left: calc(50% - (4rem / 2)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|  | ||||
							
								
								
									
										8
									
								
								resources/lang/en/dashboard/index.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								resources/lang/en/dashboard/index.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| return [ | ||||
|     'search' => 'Search for servers...', | ||||
|     'no_matches' => 'There were no servers found matching the search criteria provided.', | ||||
|     'cpu_title' => 'CPU', | ||||
|     'memory_title' => 'Memory', | ||||
| ]; | ||||
| @ -39,5 +39,5 @@ module.exports = { | ||||
|         extensions: ['*', '.js', '.vue', '.json'] | ||||
|     }, | ||||
|     plugins: [], | ||||
|     devtool: '#source-map', | ||||
|     devtool: 'source-map', | ||||
| }; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jakob Schrettenbrunner
						Jakob Schrettenbrunner