diff --git a/package.json b/package.json
index b7e523c8b..04fa752c9 100644
--- a/package.json
+++ b/package.json
@@ -3,6 +3,7 @@
"dependencies": {
"cssnano": "^4.0.3",
"date-fns": "^1.29.0",
+ "feather-icons": "^4.10.0",
"socket.io-client": "^2.1.1",
"vee-validate": "^2.1.0-beta.2",
"vue": "^2.5.7",
@@ -20,6 +21,7 @@
"@babel/plugin-transform-async-to-generator": "^7.0.0-beta.49",
"@babel/plugin-transform-runtime": "^7.0.0-beta.49",
"@babel/preset-env": "^7.0.0-beta.49",
+ "@types/feather-icons": "^4.7.0",
"@types/lodash": "^4.14.119",
"@types/node": "^10.12.15",
"@types/socket.io-client": "^1.4.32",
diff --git a/resources/assets/scripts/components/core/Icon.ts b/resources/assets/scripts/components/core/Icon.ts
new file mode 100644
index 000000000..25c06e51f
--- /dev/null
+++ b/resources/assets/scripts/components/core/Icon.ts
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import { replace } from 'feather-icons';
+
+export default Vue.component('icon', {
+ props: {
+ name: {type: String, default: 'circle'},
+ },
+ mounted: function () {
+ replace();
+ },
+ template: `
+
+ `,
+});
diff --git a/resources/assets/scripts/components/core/Modal.ts b/resources/assets/scripts/components/core/Modal.ts
new file mode 100644
index 000000000..3456e2fcb
--- /dev/null
+++ b/resources/assets/scripts/components/core/Modal.ts
@@ -0,0 +1,46 @@
+import Vue from 'vue';
+import Icon from "./Icon";
+
+export default Vue.component('modal', {
+ components: {
+ Icon,
+ },
+
+ props: {
+ modalName: { type: String, default: 'modal' },
+ show: { type: Boolean, default: false },
+ closeOnEsc: { type: Boolean, default: true },
+ },
+
+ mounted: function () {
+ if (this.$props.closeOnEsc) {
+ document.addEventListener('keydown', e => {
+ if (this.show && e.key === 'Escape') {
+ this.close();
+ }
+ })
+ }
+ },
+
+ methods: {
+ close: function () {
+ this.$emit('close', this.$props.modalName);
+ }
+ },
+
+ template: `
+
+
+
+ `
+})
diff --git a/resources/assets/scripts/components/core/Modal.vue b/resources/assets/scripts/components/core/Modal.vue
deleted file mode 100644
index 3f7db17f6..000000000
--- a/resources/assets/scripts/components/core/Modal.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
diff --git a/resources/assets/scripts/components/core/Navigation.ts b/resources/assets/scripts/components/core/Navigation.ts
new file mode 100644
index 000000000..436ac24a6
--- /dev/null
+++ b/resources/assets/scripts/components/core/Navigation.ts
@@ -0,0 +1,142 @@
+import Vue from 'vue';
+import { debounce, isObject } from 'lodash';
+import { mapState } from 'vuex';
+import {AxiosError} from "axios";
+
+export default Vue.component('navigation', {
+ data: function () {
+ return {
+ loadingResults: false,
+ searchActive: false,
+ };
+ },
+
+ computed: {
+ ...mapState('dashboard', ['servers']),
+ searchTerm: {
+ get: function (): string {
+ return this.$store.getters['dashboard/getSearchTerm'];
+ },
+ set: function (value: string): void {
+ this.$store.dispatch('dashboard/setSearchTerm', value);
+ }
+ }
+ },
+
+ created: function () {
+ document.addEventListener('click', this.documentClick);
+ },
+
+ beforeDestroy: function () {
+ document.removeEventListener('click', this.documentClick);
+ },
+
+ methods: {
+ search: debounce(function (): void {
+ // @todo why is this not liked?
+ // if (this.searchTerm.length >= 3) {
+ // this.loadingResults = true;
+ // this.gatherSearchResults();
+ // }
+ }, 500),
+
+ gatherSearchResults: function (): void {
+ this.$store.dispatch('dashboard/loadServers')
+ .catch((err: AxiosError) => {
+ console.error(err);
+
+ const response = err.response;
+ if (response && isObject(response.data.errors)) {
+ response.data.errors.forEach((error: any) => {
+ this.$flash.error(error.detail);
+ });
+ }
+ })
+ .then(() => {
+ this.loadingResults = false;
+ });
+ },
+
+ doLogout: function () {
+ this.$store.commit('auth/logout');
+ window.location.assign(this.route('auth.logout'));
+ },
+
+ documentClick: function (e: Event) {
+ if (this.$refs.searchContainer) {
+ if (this.$refs.searchContainer !== e.target && !(this.$refs.searchContainer as HTMLElement).contains(e.target as HTMLElement)) {
+ this.searchActive = false;
+ }
+ }
+ },
+ },
+
+ template: `
+
+
+
+ Pterodactyl
+
+
+
+
+
+
+
+
+
+
+ {{ server.name }}
+ {{ server.description }}
+
+
+ {{ server.node }}
+
+
+
+
+
+
+
+
+ `
+})
diff --git a/resources/assets/scripts/components/core/Navigation.vue b/resources/assets/scripts/components/core/Navigation.vue
deleted file mode 100644
index 92b485b27..000000000
--- a/resources/assets/scripts/components/core/Navigation.vue
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
-
- Pterodactyl
-
-
-
-
-
-
-
-
-
-
- {{ server.name }}
- {{ server.description }}
-
-
- {{ server.node }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/yarn.lock b/yarn.lock
index 62cc8a3f3..6ecd7d2cb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -778,6 +778,10 @@
"@shellscape/koa-send" "^4.1.0"
debug "^2.6.8"
+"@types/feather-icons@^4.7.0":
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/@types/feather-icons/-/feather-icons-4.7.0.tgz#ec66bc046bcd1513835f87541ecef54b50c57ec9"
+
"@types/lodash@^4.14.119":
version "4.14.119"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39"
@@ -1867,6 +1871,10 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classnames@^2.2.5:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+
clean-css@4.1.x:
version "4.1.11"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a"
@@ -2156,6 +2164,10 @@ core-js@^2.4.0, core-js@^2.5.0:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
+core-js@^2.5.3:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.1.tgz#87416ae817de957a3f249b3b5ca475d4aaed6042"
+
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -3143,6 +3155,13 @@ fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
+feather-icons@^4.10.0:
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/feather-icons/-/feather-icons-4.10.0.tgz#5c2ba00ecf6f0529e99ab445d054fa6bd0b9c8d6"
+ dependencies:
+ classnames "^2.2.5"
+ core-js "^2.5.3"
+
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"