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