This commit is contained in:
flash 2016-08-03 19:47:46 +02:00
parent 0dc204fcb3
commit 3d8c30e8b6
32 changed files with 178 additions and 89 deletions

View file

@ -34,7 +34,7 @@ class Controller
} }
} }
public function json($object, $operators = JSON_FORCE_OBJECT | JSON_NUMERIC_CHECK | JSON_BIGINT_AS_STRING) public function json($object, $operators = null)
{ {
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
return json_encode($object, $operators); return json_encode($object, $operators);

View file

@ -36,15 +36,15 @@ class Notification
if ($data) { if ($data) {
$data = $data[0]; $data = $data[0];
$this->id = $data->alert_id; $this->id = intval($data->alert_id);
$this->user = $data->user_id; $this->user = intval($data->user_id);
$this->time = $data->alert_timestamp; $this->time = intval($data->alert_timestamp);
$this->read = intval($data->alert_read) !== 0; $this->read = intval($data->alert_read) !== 0;
$this->title = $data->alert_title; $this->title = $data->alert_title;
$this->text = $data->alert_text; $this->text = $data->alert_text;
$this->link = $data->alert_link; $this->link = $data->alert_link;
$this->image = $data->alert_img; $this->image = $data->alert_img;
$this->timeout = $data->alert_timeout; $this->timeout = intval($data->alert_timeout);
} }
} }

View file

@ -214,13 +214,6 @@ class User
*/ */
public $youtube = ''; public $youtube = '';
/**
* The thing that indicates if it's an id or a name.
*
* @var int
*/
public $youtubeType = 0;
/** /**
* The user's steam community username. * The user's steam community username.
* *
@ -369,7 +362,6 @@ class User
$this->skype = $userRow->user_skype; $this->skype = $userRow->user_skype;
$this->discord = $userRow->user_discord; $this->discord = $userRow->user_discord;
$this->youtube = $userRow->user_youtube; $this->youtube = $userRow->user_youtube;
$this->youtubeType = intval($userRow->user_youtube_type);
$this->steam = $userRow->user_steam; $this->steam = $userRow->user_steam;
$this->osu = $userRow->user_osu; $this->osu = $userRow->user_osu;
$this->lastfm = $userRow->user_lastfm; $this->lastfm = $userRow->user_lastfm;
@ -1089,7 +1081,7 @@ class User
$alerts = []; $alerts = [];
foreach ($alertIds as $alertId) { foreach ($alertIds as $alertId) {
$alerts[$alertId] = new Notification($alertId); $alerts[] = new Notification($alertId);
} }
return $alerts; return $alerts;

View file

@ -47,9 +47,6 @@ class MoveOptionsAndProfileIntoUsers extends Migration
->nullable() ->nullable()
->default(null); ->default(null);
$table->tinyInteger('user_youtube_type')
->default(0);
$table->string('user_steam', 255) $table->string('user_steam', 255)
->nullable() ->nullable()
->default(null); ->default(null);
@ -82,7 +79,6 @@ class MoveOptionsAndProfileIntoUsers extends Migration
'user_skype', 'user_skype',
'user_discord', 'user_discord',
'user_youtube', 'user_youtube',
'user_youtube_type',
'user_steam', 'user_steam',
'user_osu', 'user_osu',
'user_lastfm', 'user_lastfm',

View file

@ -7,9 +7,9 @@ elixir(function(mix) {
mix mix
.less('aitemu/master.less', 'public/css/aitemu.css') .less('aitemu/master.less', 'public/css/aitemu.css')
.less('yuuno/master.less', 'public/css/yuuno.css') .less('yuuno/master.less', 'public/css/yuuno.css')
.typescript('app/**/*.ts', 'public/js/app.js') .typescript('Sakura/**/*.ts', 'public/js/app.js')
.typescript('aitemu/**/*.ts', 'public/js/aitemu.js') .typescript('Aitemu/**/*.ts', 'public/js/aitemu.js')
.typescript('yuuno/**/*.ts', 'public/js/yuuno.js') .typescript('Yuuno/**/*.ts', 'public/js/yuuno.js')
.scripts([ .scripts([
nodePath + 'turbolinks/dist/turbolinks.js', nodePath + 'turbolinks/dist/turbolinks.js',
], 'public/js/libraries.js'); ], 'public/js/libraries.js');

View file

@ -3,6 +3,7 @@ namespace Sakura
export class Config export class Config
{ {
public static Revision: number = 0; public static Revision: number = 0;
public static UserId: number = 0;
public static SessionId: string = ""; public static SessionId: string = "";
public static UserNameMinLength: number = 3; public static UserNameMinLength: number = 3;
public static UserNameMaxLength: number = 16; public static UserNameMaxLength: number = 16;

View file

@ -0,0 +1,15 @@
namespace Sakura
{
export interface INotification
{
id: number;
user: number;
time: number;
read: boolean;
title: string;
text: string;
link: string;
image: string;
timeout: number;
}
}

View file

@ -6,6 +6,7 @@ namespace Sakura
console.log(this.Supported()); console.log(this.Supported());
TimeAgo.Init(); TimeAgo.Init();
Friend.Init(); Friend.Init();
Notifications.Init();
} }
public static Supported(): boolean { public static Supported(): boolean {

View file

@ -0,0 +1,51 @@
namespace Sakura
{
export class Notifications
{
private static Client: AJAX;
private static IntervalContainer: number;
public static DisplayMethod: Function = (alert: INotification) => {
console.log(alert);
};
public static Init(): void
{
this.Client = new AJAX;
this.Client.SetUrl("/notifications");
this.Client.AddCallback(200, (client: AJAX) => {
Notifications.Load(<INotification[]>client.JSON());
});
this.Poll();
this.Start();
}
public static Poll(): void
{
this.Client.Start(HTTPMethod.GET);
}
public static Start(): void
{
this.IntervalContainer = setInterval(() => {
if (document.hidden) {
return;
}
Notifications.Poll();
}, 5000);
}
public static Stop(): void
{
this.Client.Stop();
clearInterval(this.IntervalContainer);
}
private static Load(alerts: INotification[]): void
{
for (var i in alerts) {
this.DisplayMethod(alerts[i]);
}
}
}
}

View file

@ -0,0 +1,28 @@
/// <reference path="../Sakura/INotification.ts" />
namespace Yuuno
{
export class Notifications
{
private static Container;
public static RegisterDisplay(): void
{
this.Container = new Sakura.DOM('notifications', Sakura.DOMSelector.ID);
Sakura.Notifications.DisplayMethod = this.Display;
}
public static Display(alert: Sakura.INotification): void
{
var id = 'yuuno-alert-' + Date.now(),
container = Sakura.DOM.Create('div', 'notification-enter', id),
icon = Sakura.DOM.Create('div', 'notification-icon'),
inner = Sakura.DOM.Create('div', 'notification-content'),
title = Sakura.DOM.Create('div', 'notification-title'),
text = Sakura.DOM.Create('div', 'notification-text'),
close = Sakura.DOM.Create('div', 'notification-close'),
closeIcon = Sakura.DOM.Create('div'),
clear = Sakura.DOM.Create('div');
}
}
}

View file

@ -5,6 +5,7 @@ namespace Yuuno
public static Startup() public static Startup()
{ {
Sakura.Main.Startup(); Sakura.Main.Startup();
Notifications.RegisterDisplay();
} }
} }
} }

View file

@ -114,37 +114,6 @@ function notifyOpen(id: string): void {
} }
} }
// Request notifications
function notifyRequest(session: string): void {
// Check if the document isn't hidden
if (document.hidden) {
return;
}
// Create AJAX object
var get = new Sakura.AJAX();
get.SetUrl('/notifications');
// Add callbacks
get.AddCallback(200, () => {
// Assign the parsed JSON
var data: Notification = JSON.parse(get.Response());
// Check if nothing went wrong
if ((typeof data).toLowerCase() === 'undefined') {
// Inform the user
throw "No or invalid data was returned";
}
// Create an object for every notification
for (var id in data) {
notifyUI(data[id]);
}
});
get.Start(Sakura.HTTPMethod.GET);
}
// Show the full page busy window // Show the full page busy window
function ajaxBusyView(show: boolean, message: string = null, type: string = null): void { function ajaxBusyView(show: boolean, message: string = null, type: string = null): void {
// Get elements // Get elements

View file

@ -39,9 +39,6 @@
<div class="centreAlign"> <div class="centreAlign">
<input class="inputStyling" type="password" id="registerPassword" name="password" onkeyup="registerVarCheck(this.id, 'password');" placeholder="Using special characters is recommended"> <input class="inputStyling" type="password" id="registerPassword" name="password" onkeyup="registerVarCheck(this.id, 'password');" placeholder="Using special characters is recommended">
</div> </div>
<div class="subLinks centreAlign">
<input class="inputStyling" name="tos" type="checkbox" id="registerToS"><label for="registerToS">I agree to the <a class="default" href="{{ route('info.terms') }}" target="_blank">Terms of Service</a>.
</div>
<div class="centreAlign"> <div class="centreAlign">
<input class="inputStyling" type="submit" name="submit" value="Register" id="registerAccBtn"> <input class="inputStyling" type="submit" name="submit" value="Register" id="registerAccBtn">
</div> </div>

View file

@ -167,6 +167,7 @@
UserNameMaxLength: {{ config('user.name_max') }}, UserNameMaxLength: {{ config('user.name_max') }},
PasswordMinEntropy: {{ config('user.pass_min_entropy') }}, PasswordMinEntropy: {{ config('user.pass_min_entropy') }},
LoggedIn: {{ user.isActive ? 'true' : 'false' }}, LoggedIn: {{ user.isActive ? 'true' : 'false' }},
UserId: {{ user.id }},
SessionId: "{{ session_id() }}", SessionId: "{{ session_id() }}",
}); });
@ -175,12 +176,6 @@
{% if config('dev.show_changelog', true) and stats %} {% if config('dev.show_changelog', true) and stats %}
Sakura.Changelog.Build(new Sakura.DOM('indexPanel', Sakura.DOMSelector.ID)); Sakura.Changelog.Build(new Sakura.DOM('indexPanel', Sakura.DOMSelector.ID));
{% endif %} {% endif %}
notifyRequest(Sakura.Config.SessionId);
setInterval(function() {
notifyRequest(Sakura.Config.SessionId);
}, 60000);
</script> </script>
</body> </body>
</html> </html>

View file

@ -4,9 +4,58 @@
{% set noUserpage = profile.userPage|length < 1 %} {% set noUserpage = profile.userPage|length < 1 %}
{% set profileView = noUserpage and profileView == 'index' ? 'comments' : profileView %} {% set title = profileHidden ? 'User not found!' : 'Profile of ' ~ profile.username %}
{% set title %}{% if profileHidden %}User not found!{% else %}Profile of {{ profile.username }}{% endif %}{% endset %} {% set youtubeIsChannelId = profile.youtube|slice(0, 2) == 'UC' and profile.youtube|length == 24 %}
{% set fields = {
"website": {
"title": "Website",
"value": profile.website,
"link": "%s",
},
"twitter": {
"title": "Twitter",
"value": profile.twitter,
"link": "https://twitter.com/%s",
"disp": "@%s",
},
"github": {
"title": "GitHub",
"value": profile.github,
"link": "https://github.com/%s",
},
"skype": {
"title": "Skype",
"value": profile.skype,
"link": "skype:%s?userinfo",
},
"discord": {
"title": "Discord",
"value": profile.discord,
},
"youtube": {
"title": "YouTube",
"value": profile.youtube,
"link": "https://youtube.com/" ~ (youtubeIsChannelId ? 'channel/' : '') ~ "%s",
"disp": youtubeIsChannelId ? profile.username ~ "'s channel" : "%s",
},
"steam": {
"title": "Steam",
"value": profile.steam,
"link": "https://steamcommunity.com/id/%s",
},
"osu": {
"title": "osu!",
"value": profile.osu,
"link": "https://osu.ppy.sh/u/%s",
},
"lastfm": {
"title": "Last.fm",
"value": profile.lastfm,
"link": "http://last.fm/user/%s",
},
} %}
{% block js %} {% block js %}
{% if not profileHidden %} {% if not profileHidden %}
@ -102,10 +151,9 @@
{% if not noUserpage %} {% if not noUserpage %}
<a class="fa fa-file-text-o" title="View {{ profile.username }}'s user page" href="#_userpage" onclick="profileMode('userpage');"></a> <a class="fa fa-file-text-o" title="View {{ profile.username }}'s user page" href="#_userpage" onclick="profileMode('userpage');"></a>
{% endif %} {% endif %}
{#<a class="fa fa-list" title="View {{ profile.username }}'s topics" href="#_topics" onclick="profileMode('topics');"></a> <a class="fa fa-list" title="View {{ profile.username }}'s topics" href="#_topics" onclick="profileMode('topics');"></a>
<a class="fa fa-reply" title="View {{ profile.username }}'s posts" href="#_posts" onclick="profileMode('posts');"></a>#} <a class="fa fa-reply" title="View {{ profile.username }}'s posts" href="#_posts" onclick="profileMode('posts');"></a>
<a class="fa fa-star" title="View {{ profile.username }}'s friends" href="#_friends" onclick="profileMode('friends');"></a> <a class="fa fa-star" title="View {{ profile.username }}'s friends" href="#_friends" onclick="profileMode('friends');"></a>
{#<a class="fa fa-users" title="View {{ profile.username }}'s groups" href="#_groups" onclick="profileMode('groups');"></a>#}
<a class="fa fa-comments-o" title="View {{ profile.username }}'s profile comments" href="#_comments" onclick="profileMode('comments');"></a> <a class="fa fa-comments-o" title="View {{ profile.username }}'s profile comments" href="#_comments" onclick="profileMode('comments');"></a>
</div> </div>
{% if user.isActive %} {% if user.isActive %}
@ -164,25 +212,21 @@
{% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %} {% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
{% if user.isActive %} {% if user.isActive %}
<table style="width: 100%;"> <table style="width: 100%;">
{% for name,field in profile.profileFields %} {% for id, data in fields %}
<tr> {% if data.value != null %}
<td style="text-align: left; font-weight: bold;"> <tr>
{{ field.name }} <td style="text-align: left; font-weight: bold;">
</td> {{ data.title }}
<td style="text-align: right;"> </td>
{% if name == 'youtube' %} <td style="text-align: right;">
<a href="https://youtube.com/{% if field.youtubetype == true %}channel{% else %}user{% endif %}/{{ field.value }}" class="default">{% if field.youtubetype == true %}{{ profile.username }}'s Channel{% else %}{{ field.value }}{% endif %}</a> {% if data.link %}
{% else %} <a href="{{ data.link|format(data.value) }}" class="default">{{ (data.disp ? data.disp : '%s')|format(data.value) }}</a>
{% if field.islink %} {% else %}
<a href="{{ field.link }}" class="default"> {{ (data.disp ? data.disp : '%s')|format(data.value) }}
{% endif %} {% endif %}
{{ field.value }} </td>
{% if field.islink %} </tr>
</a> {% endif %}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %} {% endfor %}
{% if user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %} {% if user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
<tr> <tr>

View file

@ -3,9 +3,8 @@
"module": "commonjs", "module": "commonjs",
"noImplicitAny": false, "noImplicitAny": false,
"removeComments": true, "removeComments": true,
"preserveConstEnums": true "preserveConstEnums": true,
}, "moduleResolution": "node",
"exclude": [ "rootDir": "resources/assets/typescript"
"public" }
]
} }