member listing
This commit is contained in:
parent
d579d2c8e0
commit
2d7e55f103
15 changed files with 685 additions and 9 deletions
288
assets/less/mio/classes/flag.less
Normal file
288
assets/less/mio/classes/flag.less
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
@flag-width: 16px;
|
||||||
|
@flag-height: 11px;
|
||||||
|
|
||||||
|
.flag-position(@x, @y, @offsetX: 0px, @offsetY: 0px) {
|
||||||
|
background-position: top -(@flag-height * @x) + @offsetX left -(@flag-width * @y) + @offsetY;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flag {
|
||||||
|
display: inline-block;
|
||||||
|
width: @flag-width;
|
||||||
|
height: @flag-height;
|
||||||
|
background-image: url('https://static.flash.moe/images/flag-sprite-24.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
font-size: 0;
|
||||||
|
.flag-position(23, 23); // xx
|
||||||
|
|
||||||
|
&__container {
|
||||||
|
min-width: @flag-width;
|
||||||
|
min-height: @flag-height;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--ad {.flag-position(0, 3);}
|
||||||
|
&--ae {.flag-position(0, 4);}
|
||||||
|
&--af {.flag-position(0, 5);}
|
||||||
|
&--ag {.flag-position(0, 6);}
|
||||||
|
&--ai {.flag-position(0, 8);}
|
||||||
|
&--al {.flag-position(0, 11);}
|
||||||
|
&--am {.flag-position(0, 12);}
|
||||||
|
&--an {.flag-position(0, 13);}
|
||||||
|
&--ao {.flag-position(0, 14);}
|
||||||
|
&--ar {.flag-position(0, 17);}
|
||||||
|
&--as {.flag-position(0, 18);}
|
||||||
|
&--at {.flag-position(0, 19);}
|
||||||
|
&--au {.flag-position(0, 20);}
|
||||||
|
&--aw {.flag-position(0, 22);}
|
||||||
|
&--ax {.flag-position(0, 23);}
|
||||||
|
&--az {.flag-position(0, 25);}
|
||||||
|
|
||||||
|
&--ba {.flag-position(1, 0);}
|
||||||
|
&--bb {.flag-position(1, 1);}
|
||||||
|
&--bd {.flag-position(1, 3);}
|
||||||
|
&--be {.flag-position(1, 4);}
|
||||||
|
&--bf {.flag-position(1, 5);}
|
||||||
|
&--bg {.flag-position(1, 6);}
|
||||||
|
&--bh {.flag-position(1, 7);}
|
||||||
|
&--bi {.flag-position(1, 8);}
|
||||||
|
&--bj {.flag-position(1, 9);}
|
||||||
|
&--bm {.flag-position(1, 12);}
|
||||||
|
&--bn {.flag-position(1, 13);}
|
||||||
|
&--bo {.flag-position(1, 14);}
|
||||||
|
&--br {.flag-position(1, 17);}
|
||||||
|
&--bs {.flag-position(1, 18);}
|
||||||
|
&--bt {.flag-position(1, 19);}
|
||||||
|
&--bv {.flag-position(1, 21);}
|
||||||
|
&--bw {.flag-position(1, 22);}
|
||||||
|
&--by {.flag-position(1, 24);}
|
||||||
|
&--bz {.flag-position(1, 25);}
|
||||||
|
|
||||||
|
&--ca {.flag-position(2, 0);}
|
||||||
|
&--cc {.flag-position(2, 2);}
|
||||||
|
&--cd {.flag-position(2, 3);}
|
||||||
|
&--cf {.flag-position(2, 5);}
|
||||||
|
&--cg {.flag-position(2, 6);}
|
||||||
|
&--ch {.flag-position(2, 7); width: 11px;}
|
||||||
|
&--ci {.flag-position(2, 8);}
|
||||||
|
&--ck {.flag-position(2, 10);}
|
||||||
|
&--cl {.flag-position(2, 11);}
|
||||||
|
&--cm {.flag-position(2, 12);}
|
||||||
|
&--cn {.flag-position(2, 13);}
|
||||||
|
&--co {.flag-position(2, 14);}
|
||||||
|
&--cr {.flag-position(2, 17);}
|
||||||
|
&--cs {.flag-position(2, 18);}
|
||||||
|
&--cu {.flag-position(2, 20);}
|
||||||
|
&--cv {.flag-position(2, 21);}
|
||||||
|
&--cx {.flag-position(2, 23);}
|
||||||
|
&--cy {.flag-position(2, 24);}
|
||||||
|
&--cz {.flag-position(2, 25);}
|
||||||
|
|
||||||
|
&--de {.flag-position(3, 4);}
|
||||||
|
&--dj {.flag-position(3, 9);}
|
||||||
|
&--dk {.flag-position(3, 10);}
|
||||||
|
&--dm {.flag-position(3, 12);}
|
||||||
|
&--do {.flag-position(3, 14);}
|
||||||
|
&--dz {.flag-position(3, 25);}
|
||||||
|
|
||||||
|
&--ec {.flag-position(4, 2);}
|
||||||
|
&--ee {.flag-position(4, 4);}
|
||||||
|
&--eg {.flag-position(4, 6);}
|
||||||
|
&--eh {.flag-position(4, 7);}
|
||||||
|
&--er {.flag-position(4, 17);}
|
||||||
|
&--es {.flag-position(4, 18);}
|
||||||
|
&--et {.flag-position(4, 19);}
|
||||||
|
|
||||||
|
&--fi {.flag-position(5, 8);}
|
||||||
|
&--fj {.flag-position(5, 9);}
|
||||||
|
&--fk {.flag-position(5, 10);}
|
||||||
|
&--fm {.flag-position(5, 12);}
|
||||||
|
&--fo {.flag-position(5, 14);}
|
||||||
|
&--fr {.flag-position(5, 17);}
|
||||||
|
|
||||||
|
&--ga {.flag-position(6, 0);}
|
||||||
|
&--gb {.flag-position(6, 1);}
|
||||||
|
&--gd {.flag-position(6, 3);}
|
||||||
|
&--ge {.flag-position(6, 4);}
|
||||||
|
&--gf {.flag-position(6, 5);}
|
||||||
|
&--gh {.flag-position(6, 7);}
|
||||||
|
&--gi {.flag-position(6, 8);}
|
||||||
|
&--gl {.flag-position(6, 11);}
|
||||||
|
&--gm {.flag-position(6, 12);}
|
||||||
|
&--gn {.flag-position(6, 13);}
|
||||||
|
&--gp {.flag-position(6, 15);}
|
||||||
|
&--gq {.flag-position(6, 16);}
|
||||||
|
&--gr {.flag-position(6, 17);}
|
||||||
|
&--gs {.flag-position(6, 18);}
|
||||||
|
&--gt {.flag-position(6, 19);}
|
||||||
|
&--gu {.flag-position(6, 20);}
|
||||||
|
&--gw {.flag-position(6, 22);}
|
||||||
|
&--gy {.flag-position(6, 24);}
|
||||||
|
|
||||||
|
&--hd {.flag-position(7, 3);}
|
||||||
|
&--he {.flag-position(7, 4);}
|
||||||
|
&--hk {.flag-position(7, 10);}
|
||||||
|
&--hm {.flag-position(7, 12);}
|
||||||
|
&--hn {.flag-position(7, 13);}
|
||||||
|
&--hr {.flag-position(7, 17);}
|
||||||
|
&--ht {.flag-position(7, 19);}
|
||||||
|
&--hu {.flag-position(7, 20);}
|
||||||
|
|
||||||
|
&--il {.flag-position(8, 11);}
|
||||||
|
&--in {.flag-position(8, 13);}
|
||||||
|
&--io {.flag-position(8, 14);}
|
||||||
|
&--iq {.flag-position(8, 16);}
|
||||||
|
&--ir {.flag-position(8, 17);}
|
||||||
|
&--is {.flag-position(8, 18);}
|
||||||
|
&--it {.flag-position(8, 19);}
|
||||||
|
|
||||||
|
&--jm {.flag-position(9, 12);}
|
||||||
|
&--jo {.flag-position(9, 14);}
|
||||||
|
&--jp {.flag-position(9, 15);}
|
||||||
|
|
||||||
|
&--ke {.flag-position(10, 4);}
|
||||||
|
&--kg {.flag-position(10, 6);}
|
||||||
|
&--kh {.flag-position(10, 7);}
|
||||||
|
&--ki {.flag-position(10, 8);}
|
||||||
|
&--km {.flag-position(10, 12);}
|
||||||
|
&--kn {.flag-position(10, 13);}
|
||||||
|
&--kp {.flag-position(10, 15);}
|
||||||
|
&--kr {.flag-position(10, 17);}
|
||||||
|
&--kw {.flag-position(10, 22);}
|
||||||
|
&--ky {.flag-position(10, 24);}
|
||||||
|
&--kz {.flag-position(10, 25);}
|
||||||
|
|
||||||
|
&--la {.flag-position(11, 0);}
|
||||||
|
&--lb {.flag-position(11, 1);}
|
||||||
|
&--lc {.flag-position(11, 2);}
|
||||||
|
&--li {.flag-position(11, 8);}
|
||||||
|
&--lk {.flag-position(11, 10);}
|
||||||
|
&--lr {.flag-position(11, 17);}
|
||||||
|
&--ls {.flag-position(11, 18);}
|
||||||
|
&--lt {.flag-position(11, 19);}
|
||||||
|
&--lu {.flag-position(11, 20);}
|
||||||
|
&--lv {.flag-position(11, 21);}
|
||||||
|
&--ly {.flag-position(11, 24);}
|
||||||
|
|
||||||
|
&--ma {.flag-position(12, 0);}
|
||||||
|
&--mc {.flag-position(12, 2);}
|
||||||
|
&--md {.flag-position(12, 3);}
|
||||||
|
&--me {.flag-position(12, 4, 1); height: 12px;}
|
||||||
|
&--mg {.flag-position(12, 6);}
|
||||||
|
&--mh {.flag-position(12, 7);}
|
||||||
|
&--mk {.flag-position(12, 10);}
|
||||||
|
&--ml {.flag-position(12, 11);}
|
||||||
|
&--mm {.flag-position(12, 12);}
|
||||||
|
&--mn {.flag-position(12, 13);}
|
||||||
|
&--mo {.flag-position(12, 14);}
|
||||||
|
&--mp {.flag-position(12, 15);}
|
||||||
|
&--mq {.flag-position(12, 16);}
|
||||||
|
&--mr {.flag-position(12, 17);}
|
||||||
|
&--ms {.flag-position(12, 18);}
|
||||||
|
&--mt {.flag-position(12, 19);}
|
||||||
|
&--mu {.flag-position(12, 20);}
|
||||||
|
&--mv {.flag-position(12, 21);}
|
||||||
|
&--mw {.flag-position(12, 22);}
|
||||||
|
&--mx {.flag-position(12, 23);}
|
||||||
|
&--my {.flag-position(12, 24);}
|
||||||
|
&--mz {.flag-position(12, 25);}
|
||||||
|
|
||||||
|
&--na {.flag-position(13, 0);}
|
||||||
|
&--nc {.flag-position(13, 2);}
|
||||||
|
&--ne {.flag-position(13, 4);}
|
||||||
|
&--nf {.flag-position(13, 5);}
|
||||||
|
&--ng {.flag-position(13, 6);}
|
||||||
|
&--ni {.flag-position(13, 8);}
|
||||||
|
&--nl {.flag-position(13, 11);}
|
||||||
|
&--no {.flag-position(13, 14);}
|
||||||
|
&--np {.flag-position(13, 15); width: 9px;}
|
||||||
|
&--nr {.flag-position(13, 17);}
|
||||||
|
&--nu {.flag-position(13, 20);}
|
||||||
|
&--nz {.flag-position(13, 25);}
|
||||||
|
|
||||||
|
&--ok {.flag-position(14, 10);}
|
||||||
|
|
||||||
|
&--pa {.flag-position(15, 0);}
|
||||||
|
&--pe {.flag-position(15, 4);}
|
||||||
|
&--pf {.flag-position(15, 5);}
|
||||||
|
&--pg {.flag-position(15, 6);}
|
||||||
|
&--ph {.flag-position(15, 7);}
|
||||||
|
&--pk {.flag-position(15, 10);}
|
||||||
|
&--pl {.flag-position(15, 11);}
|
||||||
|
&--pm {.flag-position(15, 12);}
|
||||||
|
&--pn {.flag-position(15, 13);}
|
||||||
|
&--pr {.flag-position(15, 17);}
|
||||||
|
&--ps {.flag-position(15, 18);}
|
||||||
|
&--pt {.flag-position(15, 19);}
|
||||||
|
&--pw {.flag-position(15, 22);}
|
||||||
|
&--py {.flag-position(15, 24);}
|
||||||
|
|
||||||
|
&--qa {.flag-position(16, 0);}
|
||||||
|
|
||||||
|
&--re {.flag-position(17, 4);}
|
||||||
|
&--ro {.flag-position(17, 14);}
|
||||||
|
&--rs {.flag-position(17, 18);}
|
||||||
|
&--ru {.flag-position(17, 20);}
|
||||||
|
&--rw {.flag-position(17, 22);}
|
||||||
|
|
||||||
|
&--sa {.flag-position(18, 0);}
|
||||||
|
&--sb {.flag-position(18, 1);}
|
||||||
|
&--sc {.flag-position(18, 2);}
|
||||||
|
&--sd {.flag-position(18, 3);}
|
||||||
|
&--se {.flag-position(18, 4);}
|
||||||
|
&--sg {.flag-position(18, 6);}
|
||||||
|
&--sh {.flag-position(18, 7);}
|
||||||
|
&--si {.flag-position(18, 8);}
|
||||||
|
&--sj {.flag-position(18, 9);}
|
||||||
|
&--sk {.flag-position(18, 10);}
|
||||||
|
&--sl {.flag-position(18, 11);}
|
||||||
|
&--sm {.flag-position(18, 12);}
|
||||||
|
&--sn {.flag-position(18, 13);}
|
||||||
|
&--so {.flag-position(18, 14);}
|
||||||
|
&--sr {.flag-position(18, 17);}
|
||||||
|
&--st {.flag-position(18, 19);}
|
||||||
|
&--sv {.flag-position(18, 21);}
|
||||||
|
&--sy {.flag-position(18, 24);}
|
||||||
|
&--sz {.flag-position(18, 25);}
|
||||||
|
|
||||||
|
&--tc {.flag-position(19, 2);}
|
||||||
|
&--td {.flag-position(19, 3);}
|
||||||
|
&--tf {.flag-position(19, 5);}
|
||||||
|
&--tg {.flag-position(19, 6);}
|
||||||
|
&--th {.flag-position(19, 7);}
|
||||||
|
&--tj {.flag-position(19, 9);}
|
||||||
|
&--tk {.flag-position(19, 10);}
|
||||||
|
&--tl {.flag-position(19, 11);}
|
||||||
|
&--tm {.flag-position(19, 12);}
|
||||||
|
&--tn {.flag-position(19, 13);}
|
||||||
|
&--to {.flag-position(19, 14);}
|
||||||
|
&--tr {.flag-position(19, 17);}
|
||||||
|
&--tt {.flag-position(19, 19);}
|
||||||
|
&--tv {.flag-position(19, 21);}
|
||||||
|
&--tw {.flag-position(19, 22);}
|
||||||
|
&--tz {.flag-position(19, 25);}
|
||||||
|
|
||||||
|
&--ua {.flag-position(20, 0);}
|
||||||
|
&--ug {.flag-position(20, 6);}
|
||||||
|
&--um {.flag-position(20, 12);}
|
||||||
|
&--us {.flag-position(20, 18);}
|
||||||
|
&--uy {.flag-position(20, 24);}
|
||||||
|
&--uz {.flag-position(20, 25);}
|
||||||
|
|
||||||
|
&--va {.flag-position(21, 0);}
|
||||||
|
&--vc {.flag-position(21, 2);}
|
||||||
|
&--ve {.flag-position(21, 4);}
|
||||||
|
&--vg {.flag-position(21, 6);}
|
||||||
|
&--vi {.flag-position(21, 8);}
|
||||||
|
&--vn {.flag-position(21, 13);}
|
||||||
|
&--vu {.flag-position(21, 20);}
|
||||||
|
|
||||||
|
&--wf {.flag-position(22, 5);}
|
||||||
|
&--ws {.flag-position(22, 18);}
|
||||||
|
|
||||||
|
&--ye {.flag-position(24, 4);}
|
||||||
|
&--yt {.flag-position(24, 19);}
|
||||||
|
|
||||||
|
&--za {.flag-position(25, 0);}
|
||||||
|
&--zm {.flag-position(25, 12);}
|
||||||
|
&--zw {.flag-position(25, 22);}
|
||||||
|
}
|
15
assets/less/mio/classes/input/select.less
Normal file
15
assets/less/mio/classes/input/select.less
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
.input__select {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
padding: 1px;
|
||||||
|
background: #fff;
|
||||||
|
color: #111;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #9475b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mio--dark .input__select {
|
||||||
|
background: #111;
|
||||||
|
color: #fff;
|
||||||
|
}
|
93
assets/less/mio/classes/members/user.less
Normal file
93
assets/less/mio/classes/members/user.less
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
.members__user {
|
||||||
|
display: flex;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
|
margin: 1px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #fbeeff;
|
||||||
|
border: 1px solid #9475b2;
|
||||||
|
box-shadow: 0 1px 2px #9475b2;
|
||||||
|
width: 396px;
|
||||||
|
transition: background-color .2s, box-shadow .2s;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 1px 1em #9475b2;
|
||||||
|
background-color: #ecddee;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__avatar {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
box-shadow: 0 1px 2px #9475b2;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__sub {
|
||||||
|
font-size: .9em;
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__country {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__flag {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__supporter {
|
||||||
|
background-image: url('https://static.flash.moe/images/tenshi.png');
|
||||||
|
width: 37px;
|
||||||
|
height: 11px;
|
||||||
|
font-size: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
font-size: .9em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stat {
|
||||||
|
width: 50%;
|
||||||
|
margin-right: 2px;
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-weight: 700;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
assets/less/mio/classes/members/users.less
Normal file
8
assets/less/mio/classes/members/users.less
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.members__users {
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
margin: 1px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ body {
|
||||||
|
|
||||||
// Input elements
|
// Input elements
|
||||||
@import "classes/input/button";
|
@import "classes/input/button";
|
||||||
|
@import "classes/input/select";
|
||||||
@import "classes/input/text";
|
@import "classes/input/text";
|
||||||
@import "classes/input/textarea";
|
@import "classes/input/textarea";
|
||||||
@import "classes/input/upload";
|
@import "classes/input/upload";
|
||||||
|
@ -44,6 +45,7 @@ body {
|
||||||
// Base styles
|
// Base styles
|
||||||
@import "classes/avatar";
|
@import "classes/avatar";
|
||||||
@import "classes/container";
|
@import "classes/container";
|
||||||
|
@import "classes/flag";
|
||||||
@import "classes/heading";
|
@import "classes/heading";
|
||||||
@import "classes/navigation";
|
@import "classes/navigation";
|
||||||
@import "classes/pagination";
|
@import "classes/pagination";
|
||||||
|
@ -78,3 +80,7 @@ body {
|
||||||
@import "classes/forum/posting";
|
@import "classes/forum/posting";
|
||||||
@import "classes/forum/topic";
|
@import "classes/forum/topic";
|
||||||
@import "classes/forum/topics";
|
@import "classes/forum/topics";
|
||||||
|
|
||||||
|
// Member listing
|
||||||
|
@import "classes/members/user";
|
||||||
|
@import "classes/members/users";
|
||||||
|
|
|
@ -44,7 +44,7 @@ function migrate_up(PDO $conn): void
|
||||||
`user_twitchtv` VARCHAR(30) NOT NULL DEFAULT '',
|
`user_twitchtv` VARCHAR(30) NOT NULL DEFAULT '',
|
||||||
`user_osu` VARCHAR(20) NOT NULL DEFAULT '',
|
`user_osu` VARCHAR(20) NOT NULL DEFAULT '',
|
||||||
`user_lastfm` VARCHAR(20) NOT NULL DEFAULT '',
|
`user_lastfm` VARCHAR(20) NOT NULL DEFAULT '',
|
||||||
`user_title` VARCHAR(64) NOT NULL DEFAULT '',
|
`user_title` VARCHAR(64) NULL DEFAULT NULL,
|
||||||
`last_seen` TIMESTAMP NULL DEFAULT NULL,
|
`last_seen` TIMESTAMP NULL DEFAULT NULL,
|
||||||
PRIMARY KEY (`user_id`),
|
PRIMARY KEY (`user_id`),
|
||||||
UNIQUE INDEX `users_username_unique` (`username`),
|
UNIQUE INDEX `users_username_unique` (`username`),
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Misuzu;
|
namespace Misuzu;
|
||||||
|
|
||||||
|
date_default_timezone_set('UTC');
|
||||||
|
|
||||||
require_once __DIR__ . '/vendor/autoload.php';
|
require_once __DIR__ . '/vendor/autoload.php';
|
||||||
require_once __DIR__ . '/src/colour.php';
|
require_once __DIR__ . '/src/colour.php';
|
||||||
require_once __DIR__ . '/src/zalgo.php';
|
require_once __DIR__ . '/src/zalgo.php';
|
||||||
|
|
|
@ -57,6 +57,7 @@ switch ($_GET['v'] ?? null) {
|
||||||
LEFT JOIN `msz_roles` as r
|
LEFT JOIN `msz_roles` as r
|
||||||
ON u.`display_role` = r.`role_id`
|
ON u.`display_role` = r.`role_id`
|
||||||
WHERE `user_id` = :user_id
|
WHERE `user_id` = :user_id
|
||||||
|
ORDER BY `user_id`
|
||||||
');
|
');
|
||||||
$getUser->bindValue('user_id', $userId);
|
$getUser->bindValue('user_id', $userId);
|
||||||
$getUser->execute();
|
$getUser->execute();
|
||||||
|
|
132
public/members.php
Normal file
132
public/members.php
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
<?php
|
||||||
|
use Misuzu\Database;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../misuzu.php';
|
||||||
|
|
||||||
|
$usersOffset = max((int)($_GET['o'] ?? 0), 0);
|
||||||
|
$usersTake = max(min((int)($_GET['t'] ?? 15), 30), 6);
|
||||||
|
|
||||||
|
$roleId = (int)($_GET['r'] ?? MSZ_ROLE_MAIN);
|
||||||
|
$orderBy = strtolower($_GET['ss'] ?? '');
|
||||||
|
$orderDir = strtoupper($_GET['sd'] ?? '');
|
||||||
|
|
||||||
|
$orderDirs = [
|
||||||
|
'ASC' => 'Ascending',
|
||||||
|
'DESC' => 'Descending',
|
||||||
|
];
|
||||||
|
|
||||||
|
$orderFields = [
|
||||||
|
'id' => [
|
||||||
|
'column' => 'user_id',
|
||||||
|
'default-dir' => 'ASC',
|
||||||
|
'title' => 'User ID',
|
||||||
|
],
|
||||||
|
'name' => [
|
||||||
|
'column' => 'username',
|
||||||
|
'default-dir' => 'ASC',
|
||||||
|
'title' => 'Username',
|
||||||
|
],
|
||||||
|
'country' => [
|
||||||
|
'column' => 'user_country',
|
||||||
|
'default-dir' => 'ASC',
|
||||||
|
'title' => 'Country',
|
||||||
|
],
|
||||||
|
'registered' => [
|
||||||
|
'column' => 'created_at',
|
||||||
|
'default-dir' => 'DESC',
|
||||||
|
'title' => 'Registration Date',
|
||||||
|
],
|
||||||
|
'last-online' => [
|
||||||
|
'column' => 'last_seen',
|
||||||
|
'default-dir' => 'DESC',
|
||||||
|
'title' => 'Last Online',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
if (empty($orderBy)) {
|
||||||
|
$orderBy = 'last-online';
|
||||||
|
} elseif (!array_key_exists($orderBy, $orderFields)) {
|
||||||
|
echo render_error(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($orderDir)) {
|
||||||
|
$orderDir = $orderFields[$orderBy]['default-dir'];
|
||||||
|
} elseif (!array_key_exists($orderDir, $orderDirs)) {
|
||||||
|
echo render_error(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = Database::connection();
|
||||||
|
$tpl = $app->getTemplating();
|
||||||
|
|
||||||
|
$getRole = $db->prepare('
|
||||||
|
SELECT
|
||||||
|
`role_id`, `role_name`, `role_colour`, `role_description`, `created_at`,
|
||||||
|
(
|
||||||
|
SELECT COUNT(`user_id`)
|
||||||
|
FROM `msz_user_roles`
|
||||||
|
WHERE `role_id` = r.`role_id`
|
||||||
|
) as `role_user_count`
|
||||||
|
FROM `msz_roles` as r
|
||||||
|
WHERE `role_id` = :role_id
|
||||||
|
');
|
||||||
|
$getRole->bindValue('role_id', $roleId);
|
||||||
|
$role = $getRole->execute() ? $getRole->fetch() : [];
|
||||||
|
|
||||||
|
if (!$role) {
|
||||||
|
echo render_error(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$getRoles = $db->prepare('
|
||||||
|
SELECT `role_id`, `role_name`, `role_colour`
|
||||||
|
FROM `msz_roles`
|
||||||
|
WHERE `role_secret` = 0
|
||||||
|
ORDER BY `role_id`
|
||||||
|
');
|
||||||
|
$roles = $getRoles->execute() ? $getRoles->fetchAll() : [];
|
||||||
|
|
||||||
|
$getUsers = $db->prepare("
|
||||||
|
SELECT
|
||||||
|
u.`user_id`, u.`username`, u.`user_country`,
|
||||||
|
u.`created_at` as `user_joined`, u.`last_seen` as `user_last_seen`,
|
||||||
|
COALESCE(u.`user_title`, r.`role_title`) as `user_title`,
|
||||||
|
COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `display_colour`,
|
||||||
|
(
|
||||||
|
SELECT COUNT(`topic_id`)
|
||||||
|
FROM `msz_forum_topics`
|
||||||
|
WHERE `user_id` = u.`user_id`
|
||||||
|
AND `topic_deleted` IS NULL
|
||||||
|
) as `user_topic_count`,
|
||||||
|
(
|
||||||
|
SELECT COUNT(`post_id`)
|
||||||
|
FROM `msz_forum_posts`
|
||||||
|
WHERE `user_id` = u.`user_id`
|
||||||
|
AND `post_deleted` IS NULL
|
||||||
|
) as `user_post_count`
|
||||||
|
FROM `msz_users` as u
|
||||||
|
LEFT JOIN `msz_roles` as r
|
||||||
|
ON r.`role_id` = u.`display_role`
|
||||||
|
LEFT JOIN `msz_user_roles` as ur
|
||||||
|
ON ur.`user_id` = u.`user_id`
|
||||||
|
WHERE ur.`role_id` = :role_id
|
||||||
|
ORDER BY u.`{$orderFields[$orderBy]['column']}` {$orderDir}
|
||||||
|
LIMIT :offset, :take
|
||||||
|
");
|
||||||
|
$getUsers->bindValue('role_id', $role['role_id']);
|
||||||
|
$getUsers->bindValue('offset', $usersOffset);
|
||||||
|
$getUsers->bindValue('take', $usersTake);
|
||||||
|
$users = $getUsers->execute() ? $getUsers->fetchAll() : [];
|
||||||
|
|
||||||
|
echo $tpl->render('user.listing', [
|
||||||
|
'roles' => $roles,
|
||||||
|
'role' => $role,
|
||||||
|
'users' => $users,
|
||||||
|
'order_fields' => $orderFields,
|
||||||
|
'order_directions' => $orderDirs,
|
||||||
|
'order_field' => $orderBy,
|
||||||
|
'order_direction' => $orderDir,
|
||||||
|
'users_offset' => $usersOffset,
|
||||||
|
'users_take' => $usersTake,
|
||||||
|
]);
|
|
@ -45,7 +45,7 @@ switch ($mode) {
|
||||||
$getProfile = Database::connection()->prepare('
|
$getProfile = Database::connection()->prepare('
|
||||||
SELECT
|
SELECT
|
||||||
u.*,
|
u.*,
|
||||||
r.`role_title` as `user_title`,
|
COALESCE(u.`user_title`, r.`role_title`) as `user_title`,
|
||||||
COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `display_colour`,
|
COALESCE(r.`role_colour`, CAST(0x40000000 AS UNSIGNED)) as `display_colour`,
|
||||||
(
|
(
|
||||||
SELECT COUNT(`topic_id`)
|
SELECT COUNT(`topic_id`)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
'News': '/news.php',
|
'News': '/news.php',
|
||||||
'Forum': '/forum/',
|
'Forum': '/forum/',
|
||||||
'Chat': 'https://chat.flashii.net',
|
'Chat': 'https://chat.flashii.net',
|
||||||
|
'Members': '/members.php',
|
||||||
} %}
|
} %}
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
{% extends '@mio/settings/master.twig' %}
|
{% extends '@mio/settings/master.twig' %}
|
||||||
{% from '@mio/macros.twig' import pagination %}
|
{% from '@mio/macros.twig' import pagination %}
|
||||||
|
|
||||||
|
{% set lhpagination = pagination(login_attempts_count, login_attempts_take, login_attempts_offset, '?m=login-history', 'settings__') %}
|
||||||
|
|
||||||
{% block settings_content %}
|
{% block settings_content %}
|
||||||
<div class="settings__description">
|
<div class="settings__description">
|
||||||
<p>These are all the login attempts to your account. If any attempt that you don't recognise is marked as successful your account may be compromised, ask a staff member for advice in this case.</p>
|
<p>These are all the login attempts to your account. If any attempt that you don't recognise is marked as successful your account may be compromised, ask a staff member for advice in this case.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings__login-history">
|
<div class="settings__login-history">
|
||||||
|
{{ lhpagination }}
|
||||||
|
|
||||||
{% for attempt in user_login_attempts %}
|
{% for attempt in user_login_attempts %}
|
||||||
<div class="settings__login-history__entry" id="attempt-{{ attempt.attempt_id }}">
|
<div class="settings__login-history__entry" id="attempt-{{ attempt.attempt_id }}">
|
||||||
<div class="settings__login-history__column settings__login-history__column--ip">
|
<div class="settings__login-history__column settings__login-history__column--ip">
|
||||||
|
@ -52,6 +56,6 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{{ pagination(login_attempts_count, login_attempts_take, login_attempts_offset, '?m=login-history', 'settings__') }}
|
{{ lhpagination }}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
{% extends '@mio/settings/master.twig' %}
|
{% extends '@mio/settings/master.twig' %}
|
||||||
{% from '@mio/macros.twig' import pagination %}
|
{% from '@mio/macros.twig' import pagination %}
|
||||||
|
|
||||||
|
{% set spagination = pagination(sessions_count, sessions_take, sessions_offset, '?m=sessions', 'settings__') %}
|
||||||
|
|
||||||
{% block settings_content %}
|
{% block settings_content %}
|
||||||
<div class="settings__description">
|
<div class="settings__description">
|
||||||
<p>These are the active logins to your account, clicking the Kill button will force a logout on that session. Your current login is highlighted with a darker purple so you don't accidentally force yourself to logout.</p>
|
<p>These are the active logins to your account, clicking the Kill button will force a logout on that session. Your current login is highlighted with a darker purple so you don't accidentally force yourself to logout.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="settings__sessions">
|
<div class="settings__sessions">
|
||||||
|
{{ spagination }}
|
||||||
|
|
||||||
{% for session in user_sessions %}
|
{% for session in user_sessions %}
|
||||||
<div class="settings__sessions__entry{% if session.session_id == active_session_id %} settings__sessions__entry--current{% endif %}" id="session-{{ session.session_id }}">
|
<div class="settings__sessions__entry{% if session.session_id == active_session_id %} settings__sessions__entry--current{% endif %}" id="session-{{ session.session_id }}">
|
||||||
<div class="settings__sessions__column settings__sessions__column--ip">
|
<div class="settings__sessions__column settings__sessions__column--ip">
|
||||||
|
@ -60,6 +64,6 @@
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{{ pagination(sessions_count, sessions_take, sessions_offset, '?m=sessions', 'settings__') }}
|
{{ spagination }}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
126
views/mio/user/listing.twig
Normal file
126
views/mio/user/listing.twig
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{% extends '@mio/user/master.twig' %}
|
||||||
|
{% from '@mio/macros.twig' import navigation, pagination %}
|
||||||
|
|
||||||
|
{% set canonical_url = '/members.php' ~ (role.role_id != 1 ? '?r=' ~ role.role_id : '') %}
|
||||||
|
{% set full_url = '/members.php?r=' ~ role.role_id ~ '&ss=' ~ order_field ~ '&sd=' ~ order_direction %}
|
||||||
|
{% set title = role.role_id == 1 ? 'Members' : 'Role » ' ~ role.role_name %}
|
||||||
|
{% set manage_link = '/manage/users.php?v=listing' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form onchange="this.submit()">
|
||||||
|
<select class="input__select" name="r"
|
||||||
|
style="color:{{ role.role_colour|colour_get_css }}">
|
||||||
|
{% for r in roles %}
|
||||||
|
<option
|
||||||
|
value="{{ r.role_id }}"
|
||||||
|
style="color:{{ r.role_colour|colour_get_css }}"
|
||||||
|
{% if r.role_id == role.role_id %} selected{% endif %}>
|
||||||
|
{{ r.role_name }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select class="input__select" name="ss">
|
||||||
|
{% for name, info in order_fields %}
|
||||||
|
<option
|
||||||
|
value="{{ name }}"
|
||||||
|
{% if name == order_field %} selected{% endif %}>
|
||||||
|
{{ info.title }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select class="input__select" name="sd">
|
||||||
|
{% for name, title in order_directions %}
|
||||||
|
<option
|
||||||
|
value="{{ name|lower }}"
|
||||||
|
{% if name == order_direction %} selected{% endif %}>
|
||||||
|
{{ title }}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<noscript>
|
||||||
|
<button class="input__button">Go</button>
|
||||||
|
</noscript>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="container members__users">
|
||||||
|
<div class="container__title">{{ title }}</div>
|
||||||
|
<div class="container__content members__users__content">
|
||||||
|
{% for user in users %}
|
||||||
|
<a class="members__user" href="/profile.php?u={{ user.user_id }}">
|
||||||
|
<div
|
||||||
|
class="avatar members__user__avatar"
|
||||||
|
style="background-image:url('/profile.php?u={{ user.user_id }}&m=avatar')">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__info">
|
||||||
|
<div
|
||||||
|
class="members__user__name"
|
||||||
|
style="color:{{ user.display_colour|colour_get_css }}">
|
||||||
|
{{ user.username }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__sub">
|
||||||
|
<div class="members__user__country">
|
||||||
|
<div class="members__user__country__name">
|
||||||
|
{{ user.user_country|country_name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flag flag--{{ user.user_country|lower }} members__user__country__flag">
|
||||||
|
{{ user.user_country }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#<div class="members__user__supporter" title="Supporter">
|
||||||
|
Supporter
|
||||||
|
</div>#}
|
||||||
|
|
||||||
|
<div class="members__user__title">
|
||||||
|
{{ user.user_title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__stats">
|
||||||
|
<div class="members__user__stat" title="{{ user.user_joined|date('r') }}">
|
||||||
|
<span class="members__user__stat__title">Joined</span>
|
||||||
|
<time class="members__user__stat__value" datetime="{{ user.user_joined|date('c') }}">
|
||||||
|
{{ user.user_joined|time_diff }}
|
||||||
|
</time>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__stat" title="{{ user.user_last_seen|date('r') }}">
|
||||||
|
<span class="members__user__stat__title">Last seen</span>
|
||||||
|
{% if user.user_last_seen is not null %}
|
||||||
|
<time class="members__user__stat__value" datetime="{{ user.user_last_seen|date('c') }}">
|
||||||
|
{{ user.user_last_seen|date('U') + 10 >= ''|date('U') ? 'just now' : user.user_last_seen|time_diff }}
|
||||||
|
</time>
|
||||||
|
{% else %}
|
||||||
|
<span class="members__user__stat__value">
|
||||||
|
Never
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__stats">
|
||||||
|
<div class="members__user__stat">
|
||||||
|
<span class="members__user__stat__title">Topics</span>
|
||||||
|
<span class="members__user__stat__value">{{ user.user_topic_count|number_format }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="members__user__stat">
|
||||||
|
<span class="members__user__stat__title">Posts</span>
|
||||||
|
<span class="members__user__stat__value">{{ user.user_post_count|number_format }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ pagination(role.role_user_count, users_take, users_offset, full_url) }}
|
||||||
|
{{ navigation(mio_navigation, '/members.php') }}
|
||||||
|
{% endblock %}
|
|
@ -106,11 +106,7 @@
|
||||||
Last Seen
|
Last Seen
|
||||||
</div>
|
</div>
|
||||||
<time class="profile__info__column" datetime="{{ profile.last_seen|date('c') }}">
|
<time class="profile__info__column" datetime="{{ profile.last_seen|date('c') }}">
|
||||||
{% if profile.last_seen|date('U') + 10 >= ''|date('U') %}
|
{{ profile.last_seen|date('U') + 10 >= ''|date('U') ? 'just now' : profile.last_seen|time_diff }}
|
||||||
just now
|
|
||||||
{% else %}
|
|
||||||
{{ profile.last_seen|time_diff }}
|
|
||||||
{% endif %}
|
|
||||||
</time>
|
</time>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
Loading…
Add table
Reference in a new issue