design stuff
This commit is contained in:
parent
c2dd8be001
commit
4b39806756
11 changed files with 455 additions and 59 deletions
|
@ -60,7 +60,7 @@ class UserController extends Controller
|
|||
Template::vars(compact('profile'));
|
||||
|
||||
// Print page contents
|
||||
return Template::render('user/profile');
|
||||
return Template::render((isset($_GET['new']) ? '@aitemu/' : '') . 'user/profile');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
margin-top: @general-spacing;
|
||||
background: no-repeat center center / cover @grey-2;
|
||||
box-shadow: 0 @global-shadow-distance @global-shadow-size fade(@grey-1, @global-shadow-opacity);
|
||||
display: flex;
|
||||
flex-flow: column-reverse;
|
||||
|
||||
&--large {
|
||||
height: 250px;
|
||||
|
@ -11,4 +13,13 @@
|
|||
&--insane {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
&__bottom {
|
||||
height: 60px;
|
||||
background: fade(@grey-0, 80%);
|
||||
display: inline-flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,9 @@
|
|||
.profile {
|
||||
text-shadow: 0 @text-shadow-distance @text-shadow-size fade(@grey-0, @text-shadow-opacity);
|
||||
|
||||
&__banner {
|
||||
display: flex;
|
||||
flex-flow: column-reverse;
|
||||
}
|
||||
|
||||
&__header {
|
||||
height: 60px;
|
||||
background: fade(@grey-0, 80%);
|
||||
padding-left: @avatar-big + (@general-spacing * 4);
|
||||
padding-right: @general-spacing * 2;
|
||||
display: inline-flex;
|
||||
flex-flow: row;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&__names {
|
||||
|
@ -24,17 +13,17 @@
|
|||
}
|
||||
|
||||
&__username {
|
||||
font-size: 2em;
|
||||
font-size: @font-size--profile-username;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: .9em;
|
||||
font-size: @font-size--profile-title;
|
||||
}
|
||||
|
||||
&__dates {
|
||||
font-weight: 300;
|
||||
text-align: right;
|
||||
font-size: .7em;
|
||||
font-size: @font-size--profile-dates;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
|
@ -57,6 +46,10 @@
|
|||
&__platform {
|
||||
text-align: left;
|
||||
margin: @general-spacing auto 0;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
|
|
140
resources/assets/less/aitemu/bem/status.less
Normal file
140
resources/assets/less/aitemu/bem/status.less
Normal file
|
@ -0,0 +1,140 @@
|
|||
.status {
|
||||
&__overall {
|
||||
font-size: @font-size--status-overall;
|
||||
font-weight: 100;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
text-align: left;
|
||||
margin-left: @general-spacing * 4;
|
||||
|
||||
&-icon {
|
||||
font-family: FontAwesome;
|
||||
}
|
||||
|
||||
&-text {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&--good {
|
||||
.status__overall-icon:before {
|
||||
content: "\f05d";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__last-update {
|
||||
align-self: flex-end;
|
||||
margin: @general-spacing * 2;
|
||||
font-size: @font-size--status-last-update;
|
||||
}
|
||||
|
||||
&__response {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__services {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
border-right: 1px solid @grey-1;
|
||||
}
|
||||
|
||||
&__service {
|
||||
display: inline-flex;
|
||||
padding: @general-spacing;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
|
||||
&-icon {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
transform: skewX(-10deg);
|
||||
background: #333;
|
||||
margin-left: @general-spacing / 2;
|
||||
box-shadow: 0 @global-shadow-distance @global-shadow-size fade(@grey-1, @global-shadow-opacity);
|
||||
}
|
||||
|
||||
&-name {
|
||||
font-size: 24px;
|
||||
text-align: right;
|
||||
flex-grow: 1;
|
||||
padding-left: @general-spacing * 10;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
background: @grey-1;
|
||||
}
|
||||
|
||||
&--good {
|
||||
.status__service-icon {
|
||||
background: @green;
|
||||
}
|
||||
}
|
||||
|
||||
&--bad {
|
||||
.status__service-icon {
|
||||
background: @red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__incident {
|
||||
display: flex;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid @grey-1;
|
||||
margin-bottom: @general-spacing;
|
||||
padding-bottom: @general-spacing;
|
||||
}
|
||||
|
||||
&-date {
|
||||
border-right: 1px solid @grey-1;
|
||||
margin-right: @general-spacing;
|
||||
padding: @general-spacing;
|
||||
padding-left: 0;
|
||||
font-size: @font-size--status-incident-date;
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
&__update {
|
||||
display: flex;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: @general-spacing;
|
||||
}
|
||||
|
||||
&-meta {
|
||||
text-align: left;
|
||||
font-style: italic;
|
||||
border-right: 1px solid @grey-1;
|
||||
padding: @general-spacing;
|
||||
margin-right: @general-spacing;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
&-text {
|
||||
padding: @general-spacing;
|
||||
}
|
||||
|
||||
&--good {
|
||||
.status__update-meta {
|
||||
border-color: @green;
|
||||
}
|
||||
}
|
||||
|
||||
&--busy {
|
||||
.status__update-meta {
|
||||
border-color: @orange;
|
||||
}
|
||||
}
|
||||
|
||||
&--bad {
|
||||
.status__update-meta {
|
||||
border-color: @red;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
@red: #b01116;
|
||||
|
||||
@green: #007c36;
|
||||
|
||||
@orange: #cf7618;
|
||||
|
||||
@grey-0: #000;
|
||||
@grey-1: #111;
|
||||
@grey-2: #222;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
@import "bem/landing";
|
||||
@import "bem/platform";
|
||||
@import "bem/profile";
|
||||
@import "bem/status";
|
||||
|
||||
@import "colours";
|
||||
@import "variables";
|
||||
|
|
|
@ -20,3 +20,11 @@
|
|||
|
||||
@header-font-size: 1.5em;
|
||||
@header-height: 50px;
|
||||
|
||||
@font-size--status-overall: 36px;
|
||||
@font-size--status-last-update: 12px;
|
||||
@font-size--status-incident-date: 24px;
|
||||
|
||||
@font-size--profile-username: 24px;
|
||||
@font-size--profile-title: 14px;
|
||||
@font-size--profile-dates: 12px;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<div class="header__navigation">
|
||||
<a class="header__entry fa-home" href="{{ route('main.index') }}">home</a>
|
||||
<a class="header__entry fa-comments" href="{{ route('forums.index') }}">forum</a>
|
||||
<a class="header__entry fa-commenting" href="{{ route('chat.redirect') }}">chat</a>
|
||||
<a class="header__entry fa-cog" href="{{ route('settings.index') }}">settings</a>
|
||||
<a class="header__entry fa-sign-out" href="{{ route('auth.logout') }}">logout</a>
|
||||
</div>
|
||||
{% if user.isActive %}
|
||||
|
@ -63,10 +63,10 @@
|
|||
<div class="container__footer">
|
||||
<div class="container__footer-copyright">flash.moe 2013-{{ ''|date('Y') }}</div>
|
||||
<div class="container__footer-links">
|
||||
<a href="#" class="container__footer-link">Terms of Service</a>
|
||||
<a href="#" class="container__footer-link">Rules</a>
|
||||
<a href="#" class="container__footer-link">Contact</a>
|
||||
<a href="#" class="container__footer-link">Status</a>
|
||||
<a href="{{ route('info.terms') }}" class="container__footer-link">Terms of Service</a>
|
||||
<a href="{{ route('info.rules') }}" class="container__footer-link">Rules</a>
|
||||
<a href="{{ route('info.contact') }}" class="container__footer-link">Contact</a>
|
||||
<a href="{{ route('status.index') }}" class="container__footer-link">Status</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
161
resources/views/aitemu/user/profile.twig
Normal file
161
resources/views/aitemu/user/profile.twig
Normal file
|
@ -0,0 +1,161 @@
|
|||
{% extends '@aitemu/master.twig' %}
|
||||
|
||||
{% set title = 'profile / ' ~ profile.username %}
|
||||
{% set banner_large = true %}
|
||||
{% set banner = profile.header ? route('user.header', profile.id) : null %}
|
||||
{% set wrapper_classes = "profile" %}
|
||||
{% set banner_classes = "profile__banner" %}
|
||||
|
||||
{% set hierarchies = {
|
||||
'founder': {
|
||||
'display': profile.id == 2,
|
||||
'icon': 'fa-cog',
|
||||
'text': 'Founder',
|
||||
},
|
||||
'staff': {
|
||||
'display': false,
|
||||
'icon': 'fa-gavel',
|
||||
'text': 'Staff',
|
||||
},
|
||||
'developer': {
|
||||
'display': false,
|
||||
'icon': 'fa-code',
|
||||
'text': 'Developer',
|
||||
},
|
||||
'contributor': {
|
||||
'display': false,
|
||||
'icon': 'fa-heart',
|
||||
'text': 'Contributor',
|
||||
},
|
||||
'premium': {
|
||||
'display': false,
|
||||
'icon': 'fa-heart',
|
||||
'text': 'Contributor',
|
||||
},
|
||||
'banned': {
|
||||
'display': false,
|
||||
'icon': 'fa-trash',
|
||||
'text': 'Banned',
|
||||
},
|
||||
} %}
|
||||
|
||||
{% set youtubeIsChannelId = profile.youtube|slice(0, 2) == 'UC' and profile.youtube|length == 24 %}
|
||||
|
||||
{% set fields = {
|
||||
"website": {
|
||||
"title": "Website",
|
||||
"icon": "fa-globe",
|
||||
"value": profile.website,
|
||||
"link": "%s",
|
||||
},
|
||||
"twitter": {
|
||||
"title": "Twitter",
|
||||
"icon": "fa-twitter",
|
||||
"value": profile.twitter,
|
||||
"link": "https://twitter.com/%s",
|
||||
"disp": "@%s",
|
||||
},
|
||||
"github": {
|
||||
"title": "GitHub",
|
||||
"icon": "fa-github",
|
||||
"value": profile.github,
|
||||
"link": "https://github.com/%s",
|
||||
},
|
||||
"skype": {
|
||||
"title": "Skype",
|
||||
"icon": "fa-skype",
|
||||
"value": profile.skype,
|
||||
"link": "skype:%s?userinfo",
|
||||
},
|
||||
"discord": {
|
||||
"title": "Discord",
|
||||
"icon": "fa-gamepad",
|
||||
"value": profile.discord,
|
||||
},
|
||||
"youtube": {
|
||||
"title": "YouTube",
|
||||
"icon": "fa-youtube-play",
|
||||
"value": profile.youtube,
|
||||
"link": "https://youtube.com/" ~ (youtubeIsChannelId ? 'channel/' : '') ~ "%s",
|
||||
"disp": youtubeIsChannelId ? profile.username ~ "'s channel" : "%s",
|
||||
},
|
||||
"steam": {
|
||||
"title": "Steam",
|
||||
"icon": "fa-steam",
|
||||
"value": profile.steam,
|
||||
"link": "https://steamcommunity.com/id/%s",
|
||||
},
|
||||
"osu": {
|
||||
"title": "osu!",
|
||||
"icon": "fa-dot-circle-o",
|
||||
"value": profile.osu,
|
||||
"link": "https://osu.ppy.sh/u/%s",
|
||||
},
|
||||
"lastfm": {
|
||||
"title": "Last.fm",
|
||||
"icon": "fa-lastfm",
|
||||
"value": profile.lastfm,
|
||||
"link": "http://last.fm/user/%s",
|
||||
},
|
||||
} %}
|
||||
|
||||
{% block banner_content %}
|
||||
<div class="banner__bottom profile__header">
|
||||
<div class="profile__header-sub profile__names">
|
||||
<div class="profile__title">{{ profile.title }}</div>
|
||||
<div class="profile__username" style="color: {{ profile.colour }}">{{ profile.username }}</div>
|
||||
</div>
|
||||
<div class="profile__header-sub profile__dates">
|
||||
<div class="profile__date--joined">Joined {# $user->joined()->format('r') #}</div>
|
||||
<div class="profile__date--last">Last seen {# $user->lastSeen()->format('r') #}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="profile__content">
|
||||
<div class="profile__container profile__container--left">
|
||||
<div class="profile__avatar" style="background-image: url('{{ route('file.avatar', profile.id) }}');"></div>
|
||||
<div class="platform profile__platform profile__hierarchies">{#
|
||||
#}{% for id, data in hierarchies %}{#
|
||||
#}{% if data.display %}
|
||||
<div class="profile__hierarchy profile__hierarchy--{{ id }}">
|
||||
<div class="profile__hierarchy-icon {{ data.icon }}"></div>
|
||||
<div class="profile__hierarchy-text">{{ data.text }}</div>
|
||||
</div>
|
||||
{% endif %}{#
|
||||
#}{% endfor %}{#
|
||||
#}</div>
|
||||
<div class="platform profile__platform profile__accounts">{#
|
||||
#}{% for id, data in fields %}{#
|
||||
#}{% if data.value != null %}
|
||||
<a class="profile__account profile__account--{{ id }}"{% if data.link %} href="{{ data.link|format(data.value) }}"{% endif %}>
|
||||
<div class="profile__account-icon fa-fw {{ data.icon }}"></div>
|
||||
<div class="profile__account-text">{{ (data.disp ? data.disp : '%s')|format(data.value) }}</div>
|
||||
</a>
|
||||
{% endif %}{#
|
||||
#}{% endfor %}{#
|
||||
#}</div>
|
||||
</div>
|
||||
<div class="profile__container profile__container--right">
|
||||
<div class="platform profile__platform profile__section profile__section--userpage">
|
||||
welcome to my userpage
|
||||
</div>
|
||||
<div class="platform profile__platform profile__section profile__section--groups">
|
||||
listing of groups
|
||||
</div>
|
||||
<div class="platform profile__platform profile__section profile__section--friends">
|
||||
listing of friends
|
||||
</div>
|
||||
<div class="platform profile__platform profile__section profile__section--achievements">
|
||||
listing of achievements
|
||||
</div>
|
||||
<div class="platform profile__platform profile__section profile__section--comments">
|
||||
profile comments
|
||||
</div>
|
||||
<div class="platform profile__platform profile__section profile__section--forum">
|
||||
listing of forum posts and created topics
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -5,12 +5,92 @@
|
|||
{% set banner_large = true %}
|
||||
|
||||
{% block banner_content %}
|
||||
{# ignore this, it's temporary #}
|
||||
<div style="display:flex;width:100%;height:100%;"><div class="fa-4x" style="align-self:center;padding:1em"><span class="fa fa-check"></span> I can write in here too!</div></div>
|
||||
<div class="banner__bottom">
|
||||
<div class="status__overall status__overall--good">
|
||||
<span class="status__overall-icon"></span> <span class="status__overall-text">all services are go!</span>
|
||||
</div>
|
||||
<div class="status__last-update">
|
||||
this is a static design preview
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="platform">
|
||||
all services are operational and i haven't designed this yet
|
||||
<div class="platform status__response">
|
||||
<div class="status__services">
|
||||
<div class="status__service status__service--good status__service--selected">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">main site</div>
|
||||
</div>
|
||||
<div class="status__service status__service--good">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">test site</div>
|
||||
</div>
|
||||
<div class="status__service status__service--bad">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">api</div>
|
||||
</div>
|
||||
<div class="status__service status__service--good">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">chat server</div>
|
||||
</div>
|
||||
<div class="status__service status__service--good">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">chat client</div>
|
||||
</div>
|
||||
<div class="status__service status__service--bad">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">irc gateway</div>
|
||||
</div>
|
||||
<div class="status__service status__service--bad">
|
||||
<div class="status__service-icon"></div>
|
||||
<div class="status__service-name">tekkit</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status__graph">graph goes here</div>
|
||||
</div>
|
||||
<div class="platform status__incidents">
|
||||
<div class="status__incident">
|
||||
<div class="status__incident-date">Aug 4, 2016</div>
|
||||
<div class="status__updates">
|
||||
<div class="status__update status__update--good">
|
||||
<div class="status__update-meta">
|
||||
<div class="status__update-time">9:01 UTC</div>
|
||||
<div class="status__update-state">Resolved</div>
|
||||
</div>
|
||||
<div class="status__update-text">
|
||||
That fixed it for some reason.
|
||||
</div>
|
||||
</div>
|
||||
<div class="status__update status__update--busy">
|
||||
<div class="status__update-meta">
|
||||
<div class="status__update-time">8:45 UTC</div>
|
||||
<div class="status__update-state">Monitoring</div>
|
||||
</div>
|
||||
<div class="status__update-text">
|
||||
Dropkicking the server out of the window.
|
||||
</div>
|
||||
</div>
|
||||
<div class="status__update status__update--bad">
|
||||
<div class="status__update-meta">
|
||||
<div class="status__update-time">8:30 UTC</div>
|
||||
<div class="status__update-state">Investigating</div>
|
||||
</div>
|
||||
<div class="status__update-text">
|
||||
Having connectivity issues with the server.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status__incident">
|
||||
<div class="status__incident-date">Aug 3, 2016</div>
|
||||
<div class="status__updates">
|
||||
<div class="status__update status__update">
|
||||
<div class="status__update-text">
|
||||
No incidents occurred.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
{% set youtubeIsChannelId = profile.youtube|slice(0, 2) == 'UC' and profile.youtube|length == 24 %}
|
||||
|
||||
{% set canViewSecret = user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
|
||||
|
||||
{% set fields = {
|
||||
"website": {
|
||||
"title": "Website",
|
||||
|
@ -55,6 +57,19 @@
|
|||
"value": profile.lastfm,
|
||||
"link": "http://last.fm/user/%s",
|
||||
},
|
||||
"email": {
|
||||
"title": "E-mail address",
|
||||
"value": canViewSecret ? profile.email : null,
|
||||
"link": "mailto:%s"
|
||||
},
|
||||
"registerip": {
|
||||
"title": "Register IP",
|
||||
"value": canViewSecret ? profile.registerIp : null,
|
||||
},
|
||||
"lastip": {
|
||||
"title": "Last IP",
|
||||
"value": canViewSecret ? profile.lastIp : null,
|
||||
},
|
||||
} %}
|
||||
|
||||
{% block js %}
|
||||
|
@ -209,45 +224,28 @@
|
|||
</tr>
|
||||
</table>
|
||||
<hr class="default">
|
||||
{% if profile.profileFields or user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
|
||||
{% if user.isActive %}
|
||||
<table style="width: 100%;">
|
||||
{% for id, data in fields %}
|
||||
{% if data.value != null %}
|
||||
<tr>
|
||||
<td style="text-align: left; font-weight: bold;">
|
||||
{{ data.title }}
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
{% if data.link %}
|
||||
<a href="{{ data.link|format(data.value) }}" class="default">{{ (data.disp ? data.disp : '%s')|format(data.value) }}</a>
|
||||
{% else %}
|
||||
{{ (data.disp ? data.disp : '%s')|format(data.value) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if user.permission(constant('Sakura\\Perms\\Manage::USE_MANAGE'), constant('Sakura\\Perms::MANAGE')) %}
|
||||
{% if user.isActive %}
|
||||
<table style="width: 100%;">
|
||||
{% for id, data in fields %}
|
||||
{% if data.value != null %}
|
||||
<tr>
|
||||
<td style="text-align: left; font-weight: bold;">E-mail address</td>
|
||||
<td style="text-align: right;"><a href="mailto:{{ profile.email }}" class="default">{{ profile.email }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: left; font-weight: bold;">Register IP</td>
|
||||
<td style="text-align: right;">{{ profile.registerIp }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align: left; font-weight: bold;">Last IP</td>
|
||||
<td style="text-align: right;">{{ profile.lastIp }}</td>
|
||||
<td style="text-align: left; font-weight: bold;">
|
||||
{{ data.title }}
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
{% if data.link %}
|
||||
<a href="{{ data.link|format(data.value) }}" class="default">{{ (data.disp ? data.disp : '%s')|format(data.value) }}</a>
|
||||
{% else %}
|
||||
{{ (data.disp ? data.disp : '%s')|format(data.value) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% else %}
|
||||
<b>Log in to view the full profile!</b>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
<b>Log in to view the full profile!</b>
|
||||
{% endif %}
|
||||
<hr class="default">
|
||||
<b>Account Standing</b>
|
||||
{% if profile.permission(constant('Sakura\\Perms\\Site::DEACTIVATED')) %}
|
||||
<h2 style="color: #888; text-shadow: 0 0 7px #888; margin-top: 0;">Deactivated</h2>
|
||||
|
|
Reference in a new issue