Skip to content

Commit 791cbaa

Browse files
committed
Get things into a somewhat working state on the login form
1 parent 7de2c86 commit 791cbaa

File tree

15 files changed

+449
-131
lines changed

15 files changed

+449
-131
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\ViewComposers;
4+
5+
use Illuminate\View\View;
6+
use Pterodactyl\Services\Helpers\AssetHashService;
7+
8+
class AssetComposer
9+
{
10+
/**
11+
* @var \Pterodactyl\Services\Helpers\AssetHashService
12+
*/
13+
private $assetHashService;
14+
15+
/**
16+
* AssetComposer constructor.
17+
*
18+
* @param \Pterodactyl\Services\Helpers\AssetHashService $assetHashService
19+
*/
20+
public function __construct(AssetHashService $assetHashService)
21+
{
22+
$this->assetHashService = $assetHashService;
23+
}
24+
25+
/**
26+
* Provide access to the asset service in the views.
27+
*
28+
* @param \Illuminate\View\View $view
29+
*/
30+
public function compose(View $view)
31+
{
32+
$view->with('asset', $this->assetHashService);
33+
}
34+
}

app/Providers/ViewComposerServiceProvider.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Pterodactyl\Providers;
44

55
use Illuminate\Support\ServiceProvider;
6+
use Pterodactyl\Http\ViewComposers\AssetComposer;
67
use Pterodactyl\Http\ViewComposers\ServerListComposer;
78
use Pterodactyl\Http\ViewComposers\Server\ServerDataComposer;
89

@@ -13,6 +14,8 @@ class ViewComposerServiceProvider extends ServiceProvider
1314
*/
1415
public function boot()
1516
{
17+
$this->app->make('view')->composer('*', AssetComposer::class);
18+
1619
$this->app->make('view')->composer('server.*', ServerDataComposer::class);
1720

1821
// Add data to make the sidebar work when viewing a server.

app/Services/Helpers/AssetHashService.php

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Pterodactyl\Services\Helpers;
44

5-
use Illuminate\Container\Container;
65
use Illuminate\Filesystem\FilesystemManager;
76
use Illuminate\Contracts\Foundation\Application;
87
use Illuminate\Contracts\Cache\Repository as CacheRepository;
@@ -56,73 +55,63 @@ public function __construct(Application $application, CacheRepository $cache, Fi
5655
*
5756
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
5857
*/
59-
public function getUrl(string $resource): string
58+
public function url(string $resource): string
6059
{
6160
$file = last(explode('/', $resource));
6261

63-
return '/' . ltrim(str_replace($file, array_get($this->getManifest(), $file, $file), $resource), '/');
62+
return '/' . ltrim(str_replace($file, array_get($this->manifest(), $file, $file), $resource), '/');
6463
}
6564

6665
/**
67-
* Get the asset manifest and store it in the cache for quicker lookups.
66+
* Return a built CSS import using the provided URL.
67+
*
68+
* @param string $resource
69+
* @return string
6870
*
69-
* @return array
7071
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
7172
*/
72-
public function getManifest(): array
73+
public function css(string $resource): string
7374
{
74-
if (! is_null(self::$manifest)) {
75-
return self::$manifest;
76-
}
77-
78-
// Skip checking the cache if we are not in production.
79-
if ($this->application->environment() === 'production') {
80-
$stored = $this->cache->get('Core:AssetManifest');
81-
if (! is_null($stored)) {
82-
return self::$manifest = $stored;
83-
}
84-
}
85-
86-
$contents = json_decode($this->filesystem->get(self::MANIFEST_PATH), true);
87-
$this->cache->put('Core:AssetManifest', $contents, 1440);
88-
89-
return self::$manifest = $contents;
75+
return '<link href="' . $this->url($resource) . '" rel="stylesheet preload" crossorigin="anonymous" referrerpolicy="no-referrer">';
9076
}
9177

9278
/**
93-
* Get the URL for a resource in a static context.
79+
* Return a built JS import using the provided URL.
9480
*
9581
* @param string $resource
9682
* @return string
9783
*
9884
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
9985
*/
100-
public static function url(string $resource): string
86+
public function js(string $resource): string
10187
{
102-
return Container::getInstance()->make(self::class)->getUrl($resource);
88+
return '<script src="' . $this->url($resource) . '" crossorigin="anonymous"></script>';
10389
}
10490

10591
/**
106-
* @param string $resource
107-
* @return string
92+
* Get the asset manifest and store it in the cache for quicker lookups.
93+
*
94+
* @return array
95+
*
10896
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
10997
*/
110-
public static function css(string $resource): string
98+
protected function manifest(): array
11199
{
112-
$path = self::url($resource);
100+
if (! is_null(self::$manifest)) {
101+
return self::$manifest;
102+
}
113103

114-
return '<link href="' . $path . '" rel="stylesheet preload" crossorigin="anonymous" referrerpolicy="no-referrer">';
115-
}
104+
// Skip checking the cache if we are not in production.
105+
if ($this->application->environment() === 'production') {
106+
$stored = $this->cache->get('Core:AssetManifest');
107+
if (! is_null($stored)) {
108+
return self::$manifest = $stored;
109+
}
110+
}
116111

117-
/**
118-
* @param string $resource
119-
* @return string
120-
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
121-
*/
122-
public static function js(string $resource): string
123-
{
124-
$path = self::url($resource);
112+
$contents = json_decode($this->filesystem->get(self::MANIFEST_PATH), true);
113+
$this->cache->put('Core:AssetManifest', $contents, 1440);
125114

126-
return '<script src="' . $path . '" crossorigin="anonymous">';
115+
return self::$manifest = $contents;
127116
}
128117
}

resources/assets/pterodactyl/css/main.css

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Vue from 'vue';
2+
import VueRouter from 'vue-router';
3+
import { Ziggy } from './helpers/ziggy';
4+
5+
// Base Vuejs Templates
6+
import Login from './components/auth/Login';
7+
8+
/**
9+
* First we will load all of this project's JavaScript dependencies which
10+
* includes Vue and other libraries. It is a great starting point when
11+
* building robust, powerful web applications using Vue and Laravel.
12+
*/
13+
14+
require('./bootstrap');
15+
16+
window.Ziggy = Ziggy;
17+
18+
/**
19+
* Next, we will create a fresh Vue application instance and attach it to
20+
* the page. Then, you may begin adding components to this application
21+
* or customize the JavaScript scaffolding to fit your unique needs.
22+
*/
23+
24+
const route = require('./../../../../vendor/tightenco/ziggy/src/js/route').default;
25+
26+
Vue.config.productionTip = false;
27+
Vue.mixin({
28+
methods: {
29+
route: route,
30+
},
31+
});
32+
33+
Vue.use(VueRouter);
34+
35+
const router = new VueRouter({
36+
routes: [
37+
{
38+
path: '/:action?',
39+
component: Login,
40+
}
41+
]
42+
});
43+
44+
const app = new Vue({
45+
router,
46+
}).$mount('#pterodactyl');
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
window._ = require('lodash');
2+
3+
/**
4+
* We'll load jQuery and the Bootstrap jQuery plugin which provides support
5+
* for JavaScript based Bootstrap features such as modals and tabs. This
6+
* code may be modified to fit the specific needs of your application.
7+
*/
8+
9+
try {
10+
window.$ = window.jQuery = require('jquery');
11+
} catch (e) {}
12+
13+
/**
14+
* We'll load the axios HTTP library which allows us to easily issue requests
15+
* to our Laravel back-end. This library automatically handles sending the
16+
* CSRF token as a header based on the value of the "XSRF" token cookie.
17+
*/
18+
19+
window.axios = require('axios');
20+
21+
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
22+
23+
/**
24+
* Next we will register the CSRF Token as a common header with Axios so that
25+
* all outgoing HTTP requests automatically have it attached. This is just
26+
* a simple convenience so we don't have to attach every token manually.
27+
*/
28+
29+
let token = document.head.querySelector('meta[name="csrf-token"]');
30+
31+
if (token) {
32+
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
33+
} else {
34+
console.error('CSRF token not found in document.');
35+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<template>
2+
<div>
3+
<form class="bg-white shadow-lg rounded-lg pt-10 px-8 pb-6 mb-4 animate fadein" method="post">
4+
<div class="flex flex-wrap -mx-3 mb-6">
5+
<div class="input-open">
6+
<input class="input" id="grid-email" type="text" aria-labelledby="grid-email" required
7+
v-bind:value="email"
8+
v-on:input="updateEmail($event)"
9+
/>
10+
<label for="grid-email">Email</label>
11+
<p class="text-grey-darker text-xs">Enter your account email address to recive instructions on resetting your password.</p>
12+
</div>
13+
</div>
14+
<div>
15+
<button class="bg-blue hover:bg-blue-dark hover:border-blue-darker border-blue-dark border text-white p-4 rounded w-full uppercase tracking-wide text-sm"
16+
type="submit">
17+
Recover Account
18+
</button>
19+
</div>
20+
<div class="pt-6 text-center">
21+
<router-link to="/" class="text-xs text-grey tracking-wide no-underline uppercase hover:text-grey-dark">
22+
Go to Login
23+
</router-link>
24+
</div>
25+
</form>
26+
</div>
27+
</template>
28+
29+
<script>
30+
export default {
31+
name: 'forgot-password',
32+
props: {
33+
email: {type: String, required: true},
34+
},
35+
methods: {
36+
updateEmail: function (event) {
37+
this.$emit('update-email', event.target.value);
38+
}
39+
}
40+
}
41+
</script>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<template>
2+
<div>
3+
<login-form
4+
v-if="this.$route.path === '/'"
5+
v-bind:email="email"
6+
v-on:update-email="onEmailUpdate"
7+
/>
8+
<forgot-password
9+
v-if="this.$route.path === '/forgot-password'"
10+
v-bind:email="email"
11+
v-on:update-email="onEmailUpdate"
12+
/>
13+
</div>
14+
</template>
15+
16+
<script>
17+
import LoginForm from "./LoginForm";
18+
import ForgotPassword from "./ForgotPassword";
19+
20+
export default {
21+
name: 'login',
22+
data: function () {
23+
return {
24+
email: '',
25+
};
26+
},
27+
methods: {
28+
onEmailUpdate: function (value) {
29+
this.$data.email = value;
30+
},
31+
},
32+
components: {
33+
ForgotPassword,
34+
LoginForm
35+
},
36+
}
37+
</script>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<template>
2+
<div>
3+
<form class="bg-white shadow-lg rounded-lg pt-10 px-8 pb-6 mb-4 animate fadein" :action="route('auth.login')" method="post">
4+
<div class="flex flex-wrap -mx-3 mb-6">
5+
<div class="input-open">
6+
<input class="input" id="grid-username" type="text" name="user" aria-labelledby="grid-username" required
7+
v-bind:value="email"
8+
v-on:input="updateEmail($event)"
9+
/>
10+
<label for="grid-username">Username or Email</label>
11+
</div>
12+
</div>
13+
<div class="flex flex-wrap -mx-3 mb-6">
14+
<div class="input-open">
15+
<input class="input" id="grid-password" type="password" name="password" aria-labelledby="grid-password" required>
16+
<label for="grid-password">Password</label>
17+
</div>
18+
</div>
19+
<div>
20+
<button class="bg-blue hover:bg-blue-dark hover:border-blue-darker border-blue-dark border text-white p-4 rounded w-full uppercase tracking-wide text-sm" type="submit">
21+
Sign In
22+
</button>
23+
</div>
24+
<div class="pt-6 text-center">
25+
<router-link to="/forgot-password" class="text-xs text-grey tracking-wide no-underline uppercase hover:text-grey-dark">
26+
Forgot Password?
27+
</router-link>
28+
</div>
29+
</form>
30+
</div>
31+
</template>
32+
33+
<script>
34+
export default {
35+
name: 'login-form',
36+
props: {
37+
email: { type: String, required: true },
38+
},
39+
methods: {
40+
updateEmail: function (event) {
41+
this.$emit('update-email', event.target.value);
42+
}
43+
}
44+
}
45+
</script>

0 commit comments

Comments
 (0)