Migrate bootstrap to version 5

This commit is contained in:
2026-08-05 13:50:06 +02:00
parent 3cfdd34b6f
commit f74dba4da6
87 changed files with 853 additions and 647 deletions
+5 -7
View File
@@ -17,7 +17,7 @@
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"bluebird": "3.5.5", "bluebird": "3.5.5",
"body-parser": "2.2.2", "body-parser": "2.2.2",
"bootstrap": "4.6.2", "bootstrap": "5.3.8",
"canvas": "3.2.1", "canvas": "3.2.1",
"canvas-toBlob": "1.0.0", "canvas-toBlob": "1.0.0",
"color-convert": "3.1.3", "color-convert": "3.1.3",
@@ -10243,10 +10243,9 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/bootstrap": { "node_modules/bootstrap": {
"version": "4.6.2", "version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", "integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"deprecated": "This version of Bootstrap is no longer supported. Please upgrade to the latest version.",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -10259,8 +10258,7 @@
], ],
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"jquery": "1.9.1 - 3", "@popperjs/core": "^2.11.8"
"popper.js": "^1.16.1"
} }
}, },
"node_modules/boxen": { "node_modules/boxen": {
+1 -1
View File
@@ -152,7 +152,7 @@
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"bluebird": "3.5.5", "bluebird": "3.5.5",
"body-parser": "2.2.2", "body-parser": "2.2.2",
"bootstrap": "4.6.2", "bootstrap": "5.3.8",
"canvas": "3.2.1", "canvas": "3.2.1",
"canvas-toBlob": "1.0.0", "canvas-toBlob": "1.0.0",
"color-convert": "3.1.3", "color-convert": "3.1.3",
+5 -4
View File
@@ -126,6 +126,7 @@ b, strong, th {
.tooltip.tooltip-pony { .tooltip.tooltip-pony {
opacity: 1; opacity: 1;
--bs-tooltip-color: #333;
.tooltip-inner { .tooltip-inner {
max-width: 300px; max-width: 300px;
@@ -134,11 +135,11 @@ b, strong, th {
border-radius: 7px; border-radius: 7px;
} }
&.bs-tooltip-top .arrow::before { &.bs-tooltip-top .tooltip-arrow::before {
border-top-color: #eee; border-top-color: #eee;
} }
&.bs-tooltip-bottom .arrow::before { &.bs-tooltip-bottom .tooltip-arrow::before {
border-bottom-color: #eee; border-bottom-color: #eee;
} }
} }
@@ -240,7 +241,7 @@ b, strong, th {
} }
.server-safe { .server-safe {
color: theme-color('success'); color: $success;
} }
.server-test { .server-test {
@@ -394,5 +395,5 @@ b, strong, th {
} }
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
@include table-row-variant($color, fade-out(theme-color-level($color, 6), 0.8)); @include table-variant($color, fade-out(tint-color($value, 48%), 0.8));
} }
+13 -6
View File
@@ -1,12 +1,16 @@
@import "../../../node_modules/bootstrap/scss/functions"; @import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables"; @import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/variables-dark";
@import "../../../node_modules/bootstrap/scss/maps";
@import "../../../node_modules/bootstrap/scss/mixins"; @import "../../../node_modules/bootstrap/scss/mixins";
// @import "../../../node_modules/bootstrap/scss/root"; @import "../../../node_modules/bootstrap/scss/utilities";
// @import "../../../node_modules/bootstrap/scss/print";
// layout & components
@import "../../../node_modules/bootstrap/scss/root";
@import "../../../node_modules/bootstrap/scss/reboot"; @import "../../../node_modules/bootstrap/scss/reboot";
@import "../../../node_modules/bootstrap/scss/type"; @import "../../../node_modules/bootstrap/scss/type";
@import "../../../node_modules/bootstrap/scss/images"; @import "../../../node_modules/bootstrap/scss/images";
@import "../../../node_modules/bootstrap/scss/code"; @import "../../../node_modules/bootstrap/scss/containers";
@import "../../../node_modules/bootstrap/scss/grid"; @import "../../../node_modules/bootstrap/scss/grid";
@import "../../../node_modules/bootstrap/scss/tables"; @import "../../../node_modules/bootstrap/scss/tables";
@import "../../../node_modules/bootstrap/scss/forms"; @import "../../../node_modules/bootstrap/scss/forms";
@@ -14,8 +18,6 @@
@import "../../../node_modules/bootstrap/scss/transitions"; @import "../../../node_modules/bootstrap/scss/transitions";
@import "../../../node_modules/bootstrap/scss/dropdown"; @import "../../../node_modules/bootstrap/scss/dropdown";
@import "../../../node_modules/bootstrap/scss/button-group"; @import "../../../node_modules/bootstrap/scss/button-group";
@import "../../../node_modules/bootstrap/scss/input-group";
@import "../../../node_modules/bootstrap/scss/custom-forms";
@import "../../../node_modules/bootstrap/scss/nav"; @import "../../../node_modules/bootstrap/scss/nav";
@import "../../../node_modules/bootstrap/scss/navbar"; @import "../../../node_modules/bootstrap/scss/navbar";
// @import "../../../node_modules/bootstrap/scss/card"; // @import "../../../node_modules/bootstrap/scss/card";
@@ -32,4 +34,9 @@
@import "../../../node_modules/bootstrap/scss/tooltip"; @import "../../../node_modules/bootstrap/scss/tooltip";
@import "../../../node_modules/bootstrap/scss/popover"; @import "../../../node_modules/bootstrap/scss/popover";
// @import "../../../node_modules/bootstrap/scss/carousel"; // @import "../../../node_modules/bootstrap/scss/carousel";
@import "../../../node_modules/bootstrap/scss/utilities";
// helpers
@import "../../../node_modules/bootstrap/scss/helpers";
// utilities
@import "../../../node_modules/bootstrap/scss/utilities/api";
+13 -7
View File
@@ -1,12 +1,16 @@
@import "../../../node_modules/bootstrap/scss/functions"; @import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables"; @import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/variables-dark";
@import "../../../node_modules/bootstrap/scss/maps";
@import "../../../node_modules/bootstrap/scss/mixins"; @import "../../../node_modules/bootstrap/scss/mixins";
// @import "../../../node_modules/bootstrap/scss/root"; @import "../../../node_modules/bootstrap/scss/utilities";
// @import "../../../node_modules/bootstrap/scss/print";
// layout & components
@import "../../../node_modules/bootstrap/scss/root";
@import "../../../node_modules/bootstrap/scss/reboot"; @import "../../../node_modules/bootstrap/scss/reboot";
@import "../../../node_modules/bootstrap/scss/type"; @import "../../../node_modules/bootstrap/scss/type";
@import "../../../node_modules/bootstrap/scss/images"; @import "../../../node_modules/bootstrap/scss/images";
@import "../../../node_modules/bootstrap/scss/code"; @import "../../../node_modules/bootstrap/scss/containers";
@import "../../../node_modules/bootstrap/scss/grid"; @import "../../../node_modules/bootstrap/scss/grid";
// @import "../../../node_modules/bootstrap/scss/tables"; // @import "../../../node_modules/bootstrap/scss/tables";
@import "../../../node_modules/bootstrap/scss/forms"; @import "../../../node_modules/bootstrap/scss/forms";
@@ -14,8 +18,6 @@
@import "../../../node_modules/bootstrap/scss/transitions"; @import "../../../node_modules/bootstrap/scss/transitions";
@import "../../../node_modules/bootstrap/scss/dropdown"; @import "../../../node_modules/bootstrap/scss/dropdown";
@import "../../../node_modules/bootstrap/scss/button-group"; @import "../../../node_modules/bootstrap/scss/button-group";
@import "../../../node_modules/bootstrap/scss/input-group";
@import "../../../node_modules/bootstrap/scss/custom-forms";
@import "../../../node_modules/bootstrap/scss/nav"; @import "../../../node_modules/bootstrap/scss/nav";
@import "../../../node_modules/bootstrap/scss/navbar"; @import "../../../node_modules/bootstrap/scss/navbar";
// @import "../../../node_modules/bootstrap/scss/card"; // @import "../../../node_modules/bootstrap/scss/card";
@@ -25,11 +27,15 @@
// @import "../../../node_modules/bootstrap/scss/jumbotron"; // @import "../../../node_modules/bootstrap/scss/jumbotron";
@import "../../../node_modules/bootstrap/scss/alert"; @import "../../../node_modules/bootstrap/scss/alert";
// @import "../../../node_modules/bootstrap/scss/progress"; // @import "../../../node_modules/bootstrap/scss/progress";
// @import "../../../node_modules/bootstrap/scss/media";
@import "../../../node_modules/bootstrap/scss/list-group"; @import "../../../node_modules/bootstrap/scss/list-group";
// @import "../../../node_modules/bootstrap/scss/close"; // @import "../../../node_modules/bootstrap/scss/close";
@import "../../../node_modules/bootstrap/scss/modal"; @import "../../../node_modules/bootstrap/scss/modal";
@import "../../../node_modules/bootstrap/scss/tooltip"; @import "../../../node_modules/bootstrap/scss/tooltip";
@import "../../../node_modules/bootstrap/scss/popover"; @import "../../../node_modules/bootstrap/scss/popover";
// @import "../../../node_modules/bootstrap/scss/carousel"; // @import "../../../node_modules/bootstrap/scss/carousel";
@import "../../../node_modules/bootstrap/scss/utilities";
// helpers
@import "../../../node_modules/bootstrap/scss/helpers";
// utilities
@import "../../../node_modules/bootstrap/scss/utilities/api";
+3 -3
View File
@@ -113,7 +113,7 @@ character-preview {
height: 400px; height: 400px;
border-radius: $border-radius-lg; border-radius: $border-radius-lg;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
width: 280px; width: 280px;
height: 280px; height: 280px;
} }
@@ -129,7 +129,7 @@ character-preview {
} }
.list-rules { .list-rules {
color: theme-color(danger) !important; color: $danger !important;
font-weight: 600; font-weight: 600;
} }
@@ -138,7 +138,7 @@ character-preview {
} }
.accessories-tabset .nav-link { .accessories-tabset .nav-link {
@include media-breakpoint-down(lg) { @include media-breakpoint-down(xl) {
padding-left: 10px; padding-left: 10px;
padding-right: 10px; padding-right: 10px;
} }
+179 -19
View File
@@ -10,7 +10,7 @@
// links // links
a.text-muted { a.text-muted {
@include hover { &:hover {
color: $link-hover-color !important; color: $link-hover-color !important;
} }
} }
@@ -67,6 +67,22 @@ code {
@include badge-variant($forbidden); @include badge-variant($forbidden);
} }
.badge-primary {
@include badge-variant($primary);
}
.badge-success {
@include badge-variant($success);
}
.badge-warning {
@include badge-variant($warning);
}
.badge-danger {
@include badge-variant($danger);
}
// dropdown / popover // dropdown / popover
.dropdown-toggle > .fa-caret-down { .dropdown-toggle > .fa-caret-down {
@@ -79,11 +95,6 @@ code {
bottom: 100%; bottom: 100%;
} }
.dropdown-menu-right {
right: 0;
left: auto;
}
.dropdown-menu-nipple-right { .dropdown-menu-nipple-right {
@include nipple(11px); @include nipple(11px);
} }
@@ -92,6 +103,13 @@ code {
color: $inverse-color; color: $inverse-color;
} }
// BS5 only right-aligns .dropdown-menu-end via popper ([data-bs-popper]); the custom
// ag-dropdown has no popper, so restore the v4 right-alignment behavior.
.dropdown-menu-end {
right: 0;
left: auto;
}
.dropdown-item, .dropdown-item:active { .dropdown-item, .dropdown-item:active {
color: inherit; color: inherit;
background-color: inherit; background-color: inherit;
@@ -140,7 +158,8 @@ code {
} }
.btn-xs { .btn-xs {
@include button-size($btn-padding-y-xs, $btn-padding-x-xs, $font-size-xs, $line-height-xs, $border-radius-xs); @include button-size($btn-padding-y-xs, $btn-padding-x-xs, $font-size-xs, $border-radius-xs);
--bs-btn-line-height: #{$line-height-xs};
} }
.btn-dark { .btn-dark {
@@ -155,18 +174,68 @@ code {
} }
} }
@each $color, $value in $theme-colors { // close button (v4 compat, dropped in v5 in favor of .btn-close)
.close {
float: right;
font-size: $font-size-base * 1.5;
font-weight: $font-weight-bold;
line-height: 1;
color: $black;
text-shadow: 0 1px 0 #fff;
opacity: 0.5;
&:hover {
color: $black;
text-decoration: none;
opacity: 0.75;
}
&:not(:disabled):not(.disabled):focus {
outline: none;
}
&:disabled,
&.disabled {
pointer-events: none;
opacity: 0.25;
}
@at-root button#{&} {
padding: 0;
background-color: transparent;
border: 0;
}
}
@each $color, $value in $theme-colors {
.btn-group, .input-group-append, .input-group-prepend { .btn-group, .input-group-append, .input-group-prepend {
> .btn-#{$color}:not(:last-child) { > .btn-#{$color}:not(:last-child) {
border-right-color: darken($value, 10%); border-end-color: darken($value, 10%);
} }
> .btn-#{$color}:not(:first-child) { > .btn-#{$color}:not(:first-child) {
border-left-color: darken($value, 10%); border-start-color: darken($value, 10%);
} }
} }
} }
// v4 solid buttons used color-yiq (150 threshold) → white text on the bright theme
// colors; BS5 color-contrast (min ratio 4.5) flips them to black. Restore white text.
@each $name in primary, success, info, warning, danger, patreon, discord {
.btn-#{$name} {
--bs-btn-color: #fff;
--bs-btn-hover-color: #fff;
--bs-btn-active-color: #fff;
--bs-btn-disabled-color: #fff;
}
.btn-outline-#{$name} {
--bs-btn-hover-color: #fff;
--bs-btn-active-color: #fff;
}
}
.btn-group-shadow { .btn-group-shadow {
box-shadow: 0 0 5px black; box-shadow: 0 0 5px black;
border-radius: $border-radius-sm; border-radius: $border-radius-sm;
@@ -184,6 +253,102 @@ code {
// form // form
label {
margin-bottom: 0.5rem;
}
// v4 .form-group (removed in BS5); the .form-inline context overrides margin to 0 below
.form-group {
margin-bottom: 1rem;
}
.form-select {
--bs-form-select-bg-img: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23ddd' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
}
.form-inline {
display: flex;
flex-flow: row wrap;
align-items: center;
.form-check {
width: 100%;
}
label {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0;
}
.form-group {
display: flex;
flex: 0 0 auto;
flex-flow: row wrap;
align-items: center;
margin-bottom: 0;
}
.form-control {
display: inline-block;
width: auto;
vertical-align: middle;
}
.input-group {
width: auto;
}
}
.input-group-prepend,
.input-group-append {
display: flex;
.btn {
position: relative;
z-index: 2;
&:focus {
z-index: 3;
}
}
.btn + .btn {
margin-left: -1px;
}
}
.input-group-prepend {
margin-right: -1px;
}
.input-group-append {
margin-left: -1px;
}
.input-group-sm > .input-group-prepend > .btn,
.input-group-sm > .input-group-append > .btn {
padding: $input-padding-y-sm $input-padding-x-sm;
font-size: 0.875rem;
line-height: 1.5;
border-radius: 2px;
}
.input-group > .input-group-prepend > .btn,
.input-group > .input-group-append:not(:last-child) > .btn,
.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group > .input-group-append > .btn,
.input-group > .input-group-prepend:not(:first-child) > .btn,
.input-group > .input-group-prepend:first-child > .btn:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.form-control[disabled] { .form-control[disabled] {
color: $input-disabled-color; color: $input-disabled-color;
} }
@@ -338,14 +503,9 @@ tabset.fixed-height {
// custom controls // custom controls
.custom-control-label { .form-check {
vertical-align: middle; .form-check-label {
} vertical-align: middle;
line-height: 1.4rem;
.modal-checkboxes {
.custom-checkbox > .custom-control-label {
&::before, &::after {
margin-top: 2px;
}
} }
} }
+11
View File
@@ -89,3 +89,14 @@
left: -6px; left: -6px;
} }
} }
@mixin alert-variant($background, $border, $color) {
--bs-alert-bg: #{$background};
--bs-alert-border-color: #{$border};
--bs-alert-color: #{$color};
}
@mixin badge-variant($bg) {
color: color-contrast($bg);
background-color: $bg;
}
+37 -15
View File
@@ -75,8 +75,6 @@ $chat-colors: (
whisper-announcement: $chat-whisper whisper-announcement: $chat-whisper
); );
$enable-print-styles: false;
$spacer: 16px; $spacer: 16px;
// body // body
@@ -91,6 +89,9 @@ $dark-bg: darken($body-bg, 7%);
// links // links
$link-color: #d88856; $link-color: #d88856;
$link-hover-color: lighten($link-color, 15%); $link-hover-color: lighten($link-color, 15%);
// v4 had no default underline; BS5 defaults to underline.
$link-decoration: none;
$link-hover-decoration: underline;
// fonts // fonts
// $font-family-sans-serif: 'Helvetica Neue', Helvetica, Arial, sans-serif; // $font-family-sans-serif: 'Helvetica Neue', Helvetica, Arial, sans-serif;
@@ -123,6 +124,7 @@ $nav-tabs-link-active-color: #eee;
$nav-link-hover-bg: fade-out(#000, 0.7); $nav-link-hover-bg: fade-out(#000, 0.7);
// components // components
$border-radius: 4px;
$border-radius-base: 3px; $border-radius-base: 3px;
$border-radius-lg: 4px; $border-radius-lg: 4px;
$border-radius-sm: 2px; $border-radius-sm: 2px;
@@ -131,8 +133,10 @@ $border-radius-xs: 2px;
// buttons // buttons
$input-btn-focus-color: rgba($focus-color, .3); $input-btn-focus-color: rgba($focus-color, .3);
$input-focus-border-color: lighten($focus-color, 10); $input-focus-border-color: lighten($focus-color, 10);
$input-btn-padding-y-sm: .375rem; $btn-padding-y-sm: .375rem;
$input-btn-padding-x-sm: .65rem; $btn-padding-x-sm: .65rem;
$input-padding-y-sm: .375rem;
$input-padding-x-sm: .65rem;
$btn-padding-x-xs: 5px; $btn-padding-x-xs: 5px;
$btn-padding-y-xs: 1px; $btn-padding-y-xs: 1px;
$font-size-xs: 0.858rem; $font-size-xs: 0.858rem;
@@ -140,8 +144,26 @@ $line-height-xs: 17px;
$btn-default-color: #333; $btn-default-color: #333;
// dropdown // dropdown
$dropdown-bg: #fff;
$dropdown-color: $inverse-color;
$dropdown-link-color: $inverse-color;
$dropdown-link-hover-color: darken($inverse-color, 5%);
$dropdown-link-disabled-color: #a6acb1; $dropdown-link-disabled-color: #a6acb1;
// popover (v4 had white popovers; BS5.3 defaults $popover-bg to the body bg)
$popover-bg: #fff;
$popover-header-bg: #fff;
$popover-header-color: $inverse-color;
$popover-border-color: rgba(0, 0, 0, .2);
// tooltip (BS5.3 ties tooltip colors to body/emphasis; keep dark bg + light text)
$tooltip-bg: var(--bs-body-bg);
$tooltip-color: var(--bs-body-color);
// emphasis (BS5.3 defaults to black; the dark theme needs light emphasis text for
// tables, navbar, nav active states and list-group hover)
$body-emphasis-color: $body-color;
// forms // forms
$input-bg: #222; $input-bg: #222;
$input-color: #ddd; $input-color: #ddd;
@@ -150,16 +172,14 @@ $input-disabled-color: darken($input-color, 35%);
$input-border-color: $border-color; $input-border-color: $border-color;
// custom controls // custom controls
$custom-control-indicator-focus-box-shadow: 0 0 0 3px rgba($focus-color, .5); $form-check-input-width: 1.2em;
$custom-control-indicator-size: 1.2rem; $form-check-input-border: 1px solid $border-color;
// $custom-control-gutter: 1.7rem; $form-check-input-checked-color: white;
$custom-control-indicator-checked-bg: $secondary; $form-check-input-checked-bg-color: $secondary;
$custom-control-indicator-checked-disabled-bg: rgba($secondary, .5); $form-check-input-checked-border-color: $secondary;
$custom-control-label-disabled-color: $text-muted; $form-check-input-focus-box-shadow: 0 0 0 3px rgba($focus-color, .5);
$custom-control-indicator-active-bg: rgba($secondary, .6); $form-check-input-disabled-opacity: .5;
$custom-control-indicator-checked-color: white; $form-check-label-disabled-opacity: .5;
$custom-control-indicator-bg-size: 65% 65%;
$custom-control-indicator-border-color: $border-color;
// modals // modals
$modal-content-bg: $dark-bg; $modal-content-bg: $dark-bg;
@@ -168,7 +188,8 @@ $modal-header-border-color: #444;
$modal-footer-border-color: $modal-header-border-color; $modal-footer-border-color: $modal-header-border-color;
// tables // tables
$table-sm-cell-padding: 0.4rem; $table-cell-padding-y-sm: 0.4rem;
$table-cell-padding-x-sm: 0.4rem;
$table-border-color: #6c757d; $table-border-color: #6c757d;
$table-hover-bg: #3a3a3a; $table-hover-bg: #3a3a3a;
@@ -205,3 +226,4 @@ $flag-green: #00aa00;
@import "../../../node_modules/bootstrap/scss/functions"; @import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables"; @import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/mixins"; @import "../../../node_modules/bootstrap/scss/mixins";
@import "mixins";
+1 -1
View File
@@ -19,7 +19,7 @@ export function createSupporterChanges(entries: LogEntry[]): SupporterChange[] {
const current = changes[i]; const current = changes[i];
if (current.date.getMonth() !== prev.date.getMonth()) { if (current.date.getMonth() !== prev.date.getMonth()) {
current.class += ' border-left border-success pl-2'; current.class += ' border-start border-success ps-2';
} }
if (current.added && prev.added) { if (current.added && prev.added) {
@@ -3,7 +3,7 @@ div(*ngIf="account")
.col-md-12 .col-md-12
h2 h2
| {{account.name}} | {{account.name}}
small.text-muted.ml-1 small.text-muted.ms-1
em {{account.name | translit}} em {{account.name | translit}}
.row .row
@@ -15,25 +15,25 @@ div(*ngIf="account")
.mb-2 .mb-2
div div
span.text-muted created: span.text-muted created:
from-now.ml-1([time]="account.createdAt") from-now.ms-1([time]="account.createdAt")
span.text-muted.ml-1 ({{account.createdAt | date}}) span.text-muted.ms-1 ({{account.createdAt | date}})
div div
span.text-muted last visit: span.text-muted last visit:
from-now.ml-1([time]="account.lastVisit") from-now.ms-1([time]="account.lastVisit")
span.text-muted.ml-1 ({{account.lastVisit | date}}) span.text-muted.ms-1 ({{account.lastVisit | date}})
div div
span.text-muted last browser: span.text-muted last browser:
ua-info.ml-1([userAgent]="accountObject?.lastUserAgent") ua-info.ms-1([userAgent]="accountObject?.lastUserAgent")
div div
span.text-muted age: span.text-muted age:
span([class.text-strike]="account.birthyear") span([class.text-strike]="account.birthyear")
span.ml-1 {{age}} span.ms-1 {{age}}
span.text-muted.ml-1 ({{account.birthdate | date:'yyyy-MM-dd'}}) span.text-muted.ms-1 ({{account.birthdate | date:'yyyy-MM-dd'}})
span(*ngIf="account.birthyear") span(*ngIf="account.birthyear")
span.ml-1 {{forceAge}} span.ms-1 {{forceAge}}
span.text-muted.ml-1 ({{account.birthyear}}) span.text-muted.ms-1 ({{account.birthyear}})
.d-inline-block.dropdown(dropdown) .d-inline-block.dropdown(dropdown)
a.icon-button.ml-1(dropdownToggle) a.icon-button.ms-1(dropdownToggle)
fa-icon([icon]="cogIcon") fa-icon([icon]="cogIcon")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item((click)="setAge(-1)") button.dropdown-item((click)="setAge(-1)")
@@ -44,21 +44,21 @@ div(*ngIf="account")
.d-flex.justify-content-between.align-items-start .d-flex.justify-content-between.align-items-start
h5 Counters h5 Counters
div div
button.btn.btn-xs.btn-default.ml-1((click)="refreshDetails()" title="Refresh account details") button.btn.btn-xs.btn-default.ms-1((click)="refreshDetails()" title="Refresh account details")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.mb-2 .mb-2
div(*ngFor="let counter of counters") div(*ngFor="let counter of counters")
span.text-muted {{counter.key}}: span.text-muted {{counter.key}}:
span.ml-1 {{counter.value}} span.ms-1 {{counter.value}}
.d-flex.justify-content-between.align-items-start .d-flex.justify-content-between.align-items-start
h5 Status h5 Status
div div
button.btn.btn-xs.btn-default.ml-1((click)="clearSessions()" title="Sign out user" [disabled]="clearingSessions") button.btn.btn-xs.btn-default.ms-1((click)="clearSessions()" title="Sign out user" [disabled]="clearingSessions")
fa-icon([icon]="clearingSessions ? spinnerIcon : signOutIcon" [fixedWidth]="true" [animation]="clearingSessions ? 'spin' : undefined") fa-icon([icon]="clearingSessions ? spinnerIcon : signOutIcon" [fixedWidth]="true" [animation]="clearingSessions ? 'spin' : undefined")
button.btn.btn-xs.btn-default.ml-1((click)="showAccountData()" title="Fetch account data (in console)") button.btn.btn-xs.btn-default.ms-1((click)="showAccountData()" title="Fetch account data (in console)")
fa-icon([icon]="consoleIcon" [fixedWidth]="true") fa-icon([icon]="consoleIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1((click)="accountStatus.refresh()" title="Refresh status") button.btn.btn-xs.btn-default.ms-1((click)="accountStatus.refresh()" title="Refresh status")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.mb-2 .mb-2
@@ -69,13 +69,13 @@ div(*ngIf="account")
.btn-group.btn-group-sm .btn-group.btn-group-sm
button.btn(*ngFor="let r of roles" [btnHighlight]="hasRole(r)" (click)="toggleRole(r)" [disabled]="!canToggleRole(r)") button.btn(*ngFor="let r of roles" [btnHighlight]="hasRole(r)" (click)="toggleRole(r)" [disabled]="!canToggleRole(r)")
| {{r}} | {{r}}
button.btn.btn-sm.btn-danger.ml-1((click)="remove()" [disabled]="!canRemove" title="Delete account") button.btn.btn-sm.btn-danger.ms-1((click)="remove()" [disabled]="!canRemove" title="Delete account")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.d-flex.justify-content-between.align-items-start .d-flex.justify-content-between.align-items-start
h5 h5
| Notes | Notes
a.text-muted.ml-1([href]="translateUrl(account.note)" target="_blank" title="Translate note") a.text-muted.ms-1([href]="translateUrl(account.note)" target="_blank" title="Translate note")
fa-icon([icon]="langIcon") fa-icon([icon]="langIcon")
.text-muted .text-muted
from-now([time]="account.noteUpdated") from-now([time]="account.noteUpdated")
@@ -85,7 +85,7 @@ div(*ngIf="account")
.d-flex.justify-content-between.align-items-start .d-flex.justify-content-between.align-items-start
h5 Merges #[span.text-muted ({{merges?.length || 0}})] h5 Merges #[span.text-muted ({{merges?.length || 0}})]
div div
button.btn.btn-xs.btn-default.ml-1((click)="refreshDetails()" title="Refresh account details") button.btn.btn-xs.btn-default.ms-1((click)="refreshDetails()" title="Refresh account details")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
table.table.table-sm(*ngIf="merges?.length") table.table.table-sm(*ngIf="merges?.length")
@@ -106,11 +106,11 @@ div(*ngIf="account")
.d-flex .d-flex
.flex-grow-1 .flex-grow-1
time-field([time]="m.date") time-field([time]="m.date")
.dropdown.float-right(dropdown) .dropdown.float-end(dropdown)
button.btn.btn-xs.btn-default.dropdown-toggle( button.btn.btn-xs.btn-default.dropdown-toggle(
dropdownToggle [tooltip]="(m.reason || '[null reason]') + (m.split ? ' (split)' : '')") dropdownToggle [tooltip]="(m.reason || '[null reason]') + (m.split ? ' (split)' : '')")
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
button.dropdown-item((click)="printMerge(m)") button.dropdown-item((click)="printMerge(m)")
| Print merge info | Print merge info
button.dropdown-item((click)="printMerge2(m)") button.dropdown-item((click)="printMerge2(m)")
@@ -134,10 +134,10 @@ div(*ngIf="account")
//- tbody //- tbody
//- tr(*ngFor="let l of support") //- tr(*ngFor="let l of support")
//- td //- td
//- fa-icon.mr-1([icon]="l.icon" [ngClass]="l.class") //- fa-icon.me-1([icon]="l.icon" [ngClass]="l.class")
//- | {{l.message}} //- | {{l.message}}
//- td //- td
//- time-field.mr-2([time]="l.date") //- time-field.me-2([time]="l.date")
//- span.text-muted ({{l.date | date:'MMM d'}}) //- span.text-muted ({{l.date | date:'MMM d'}})
h5 Ban log #[span.text-muted ({{banLog?.length || 0}})] h5 Ban log #[span.text-muted ({{banLog?.length || 0}})]
@@ -158,7 +158,7 @@ div(*ngIf="account")
.dropdown(dropdown) .dropdown(dropdown)
button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle)
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="fetchAuths()") a.dropdown-item((click)="fetchAuths()")
| Fetch auths data | Fetch auths data
a.dropdown-item((click)="printAuthList()") a.dropdown-item((click)="printAuthList()")
@@ -184,20 +184,20 @@ div(*ngIf="account")
h5 Origins #[span.text-muted ({{origins.length}})] h5 Origins #[span.text-muted ({{origins.length}})]
div div
button.btn.btn-xs.btn-default((click)="clearOrigins(true, true)" title="Remove all origins older than 14 days used by only one account") button.btn.btn-xs.btn-default((click)="clearOrigins(true, true)" title="Remove all origins older than 14 days used by only one account")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| old single | old single
button.btn.btn-xs.btn-default.ml-1((click)="clearOrigins(true, false)" title="Remove all origins older than 14 days") button.btn.btn-xs.btn-default.ms-1((click)="clearOrigins(true, false)" title="Remove all origins older than 14 days")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| old | old
button.btn.btn-xs.btn-default.ml-1((click)="clearOrigins(false, true)" title="Remove all origins used by only one account") button.btn.btn-xs.btn-default.ms-1((click)="clearOrigins(false, true)" title="Remove all origins used by only one account")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| single | single
button.btn.btn-xs.btn-default.ml-1((click)="clearOrigins(false, false)" title="Remove all origins") button.btn.btn-xs.btn-default.ms-1((click)="clearOrigins(false, false)" title="Remove all origins")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| all | all
.dropdown.d-inline-block.ml-1(dropdown) .dropdown.d-inline-block.ms-1(dropdown)
button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle title="Remove all origins in region") button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle title="Remove all origins in region")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| region | region
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let region of originRegions" (click)="clearOriginsInRegion(region)") a.dropdown-item(*ngFor="let region of originRegions" (click)="clearOriginsInRegion(region)")
@@ -206,7 +206,7 @@ div(*ngIf="account")
.d-flex.align-items-center.mb-1(*ngFor="let o of origins") .d-flex.align-items-center.mb-1(*ngFor="let o of origins")
origin-info-remote.flex-grow-1([originIP]="o.ip") origin-info-remote.flex-grow-1([originIP]="o.ip")
small.text-muted small.text-muted
from-now.mr-1([time]="o.last") from-now.me-1([time]="o.last")
button.btn.btn-xs.btn-default((click)="removeOrigin(o.ip)" title="Remove origin") button.btn.btn-xs.btn-default((click)="removeOrigin(o.ip)" title="Remove origin")
fa-icon([icon]="trashIcon") fa-icon([icon]="trashIcon")
@@ -216,12 +216,12 @@ div(*ngIf="account")
.d-flex.justify-content-between.align-items-start .d-flex.justify-content-between.align-items-start
h5 h5
| Duplicates #[span.text-muted ({{duplicates?.length}})] | Duplicates #[span.text-muted ({{duplicates?.length}})]
fa-icon.text-muted.ml-1(*ngIf="loadingDuplicates" [icon]="spinnerIcon" [fixedWidth]="true" animation="spin") fa-icon.text-muted.ms-1(*ngIf="loadingDuplicates" [icon]="spinnerIcon" [fixedWidth]="true" animation="spin")
div div
button.btn.btn-xs.btn-default((click)="clearOriginsFromDuplicates()" title="Remove all origins older than 14 days from all duplicates") button.btn.btn-xs.btn-default((click)="clearOriginsFromDuplicates()" title="Remove all origins older than 14 days from all duplicates")
fa-icon.mr-1([icon]="trashIcon") fa-icon.me-1([icon]="trashIcon")
| old | old
button.btn.btn-xs.btn-default.ml-1((click)="refresh()" title="Refresh duplicates") button.btn.btn-xs.btn-default.ms-1((click)="refresh()" title="Refresh duplicates")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.mb-2 .mb-2
@@ -230,34 +230,34 @@ div(*ngIf="account")
.mb-1.d-flex.align-items-center(*ngFor="let d of duplicates | slice:0:duplicatesLimit") .mb-1.d-flex.align-items-center(*ngFor="let d of duplicates | slice:0:duplicatesLimit")
ng-template(#duplicatePonies) ng-template(#duplicatePonies)
.text-left(*ngIf="d.ponies") .text-start(*ngIf="d.ponies")
div(*ngFor="let p of d.ponies") div(*ngFor="let p of d.ponies")
| {{p}} | {{p}}
span.badge.badge-none(title="Duplicate origins" [class.deleted]="d.origins === 0") span.badge.badge-none(title="Duplicate origins" [class.deleted]="d.origins === 0")
| {{d.origins}} | {{d.origins}}
span.badge.badge-none.ml-1( span.badge.badge-none.ms-1(
title="Duplicate ponies" [class.deleted]="!d.ponies || !d.ponies.length" title="Duplicate ponies" [class.deleted]="!d.ponies || !d.ponies.length"
[tooltip]="duplicatePonies" [isDisabled]="!d.ponies || !d.ponies.length") [tooltip]="duplicatePonies" [isDisabled]="!d.ponies || !d.ponies.length")
| {{d.ponies ? d.ponies.length : '-'}} | {{d.ponies ? d.ponies.length : '-'}}
fa-icon.ml-1.text-alert( fa-icon.ms-1.text-alert(
*ngIf="d.note" [icon]="duplicateNoteIcon" title="Duplicate in note") *ngIf="d.note" [icon]="duplicateNoteIcon" title="Duplicate in note")
fa-icon.ml-1.text-muted( fa-icon.ms-1.text-muted(
*ngIf="d.browserId" [icon]="duplicateBrowserIdIcon" title="Duplicate browser ID") *ngIf="d.browserId" [icon]="duplicateBrowserIdIcon" title="Duplicate browser ID")
fa-icon.ml-1.text-muted( fa-icon.ms-1.text-muted(
*ngIf="d.userAgent" [icon]="duplicateBrowserIcon" [tooltip]="d.userAgent" title="Duplicate browser") *ngIf="d.userAgent" [icon]="duplicateBrowserIcon" [tooltip]="d.userAgent" title="Duplicate browser")
fa-icon.ml-1( fa-icon.ms-1(
*ngIf="d.emails" [icon]="duplicateEmailIcon" title="Duplicate emails: {{d.emails}}" *ngIf="d.emails" [icon]="duplicateEmailIcon" title="Duplicate emails: {{d.emails}}"
[ngClass]="d.indenticalEmail ? 'text-alert' : 'text-muted'") [ngClass]="d.indenticalEmail ? 'text-alert' : 'text-muted'")
fa-icon.ml-1.text-alert(*ngIf="d.birthdate" [icon]="duplicateBirthdateIcon" title="Duplicate birthdate") fa-icon.ms-1.text-alert(*ngIf="d.birthdate" [icon]="duplicateBirthdateIcon" title="Duplicate birthdate")
fa-icon.ml-1.text-muted(*ngIf="d.name" [icon]="duplicateNameIcon" title="Duplicate name") fa-icon.ms-1.text-muted(*ngIf="d.name" [icon]="duplicateNameIcon" title="Duplicate name")
account-info-remote.ml-1(#info [accountId]="d.account" [extendedAuths]="true") account-info-remote.ms-1(#info [accountId]="d.account" [extendedAuths]="true")
button.btn.btn-xs.btn-default.ml-1((click)="merge(d.account)" title="Merge account") button.btn.btn-xs.btn-default.ms-1((click)="merge(d.account)" title="Merge account")
fa-icon([icon]="mergeIcon" size="lg") fa-icon([icon]="mergeIcon" size="lg")
button.btn.btn-xs.btn-default.ml-1((click)="chatLog.add(info.account)" title="Add to chat log") button.btn.btn-xs.btn-default.ms-1((click)="chatLog.add(info.account)" title="Add to chat log")
fa-icon([icon]="commentIcon" [fixedWidth]="true") fa-icon([icon]="commentIcon" [fixedWidth]="true")
a.text-muted(*ngIf="duplicates && duplicates.length > duplicatesLimit" (click)="duplicatesLimit = 9999999") a.text-muted(*ngIf="duplicates && duplicates.length > duplicatesLimit" (click)="duplicatesLimit = 9999999")
@@ -277,13 +277,13 @@ div(*ngIf="account")
.mb-1.d-flex.align-items-center(*ngFor="let a of around") .mb-1.d-flex.align-items-center(*ngFor="let a of around")
span.badge.badge-none(title="Distance in tiles from user") {{a.distance.toFixed(1)}} span.badge.badge-none(title="Distance in tiles from user") {{a.distance.toFixed(1)}}
fa-icon.ml-1.text-alert(*ngIf="a.party" [icon]="partyIcon" title="In party with user") fa-icon.ms-1.text-alert(*ngIf="a.party" [icon]="partyIcon" title="In party with user")
account-info-remote.ml-1(#info [accountId]="a.account" [extendedAuths]="true" [showDuplicates]="true") account-info-remote.ms-1(#info [accountId]="a.account" [extendedAuths]="true" [showDuplicates]="true")
button.btn.btn-xs.btn-default.ml-1((click)="merge(a.account)" title="Merge account") button.btn.btn-xs.btn-default.ms-1((click)="merge(a.account)" title="Merge account")
fa-icon([icon]="mergeIcon" size="lg") fa-icon([icon]="mergeIcon" size="lg")
button.btn.btn-xs.btn-default.ml-1((click)="chatLog.add(info.account)" title="Add to chat log") button.btn.btn-xs.btn-default.ms-1((click)="chatLog.add(info.account)" title="Add to chat log")
fa-icon([icon]="commentIcon" [fixedWidth]="true") fa-icon([icon]="commentIcon" [fixedWidth]="true")
hr hr
@@ -297,7 +297,7 @@ div(*ngIf="account")
.mb-2 .mb-2
.mb-1.d-flex.align-items-center(*ngFor="let a of friends | slice:0:friendsLimit") .mb-1.d-flex.align-items-center(*ngFor="let a of friends | slice:0:friendsLimit")
account-info-remote([accountId]="a") account-info-remote([accountId]="a")
button.btn.btn-xs.btn-default.ml-1((click)="removeFriend(a)" title="Remove friend") button.btn.btn-xs.btn-default.ms-1((click)="removeFriend(a)" title="Remove friend")
fa-icon([icon]="trashIcon") fa-icon([icon]="trashIcon")
a.text-muted(*ngIf="friends && friends.length > friendsLimit" (click)="friendsLimit = 9999999") a.text-muted(*ngIf="friends && friends.length > friendsLimit" (click)="friendsLimit = 9999999")
| more ... | more ...
@@ -306,10 +306,10 @@ div(*ngIf="account")
//- h5 Supporter invites #[span.text-muted ({{invites?.length || 0}})] //- h5 Supporter invites #[span.text-muted ({{invites?.length || 0}})]
//- div(*ngIf="invites?.length") //- div(*ngIf="invites?.length")
.mb-1.d-flex.align-items-center(*ngFor="let i of invites") .mb-1.d-flex.align-items-center(*ngFor="let i of invites")
.text-muted.mr-2 {{i.type}} .text-muted.me-2 {{i.type}}
fa-icon.mr-2([icon]="checkIcon" [ngClass]="i.active ? 'text-success' : 'text-danger'") fa-icon.me-2([icon]="checkIcon" [ngClass]="i.active ? 'text-success' : 'text-danger'")
account-info-remote.ml-1([accountId]="i.target" [extendedAuths]="true") account-info-remote.ms-1([accountId]="i.target" [extendedAuths]="true")
small.text-muted.flex-grow-1.text-right small.text-muted.flex-grow-1.text-end
time-field([time]="i.createdAt") time-field([time]="i.createdAt")
hr hr
@@ -372,7 +372,7 @@ div(*ngIf="account")
.mb-2 .mb-2
.mb-1.d-flex.align-items-center(*ngFor="let a of ignoredBy | slice:0:ignoredByLimit") .mb-1.d-flex.align-items-center(*ngFor="let a of ignoredBy | slice:0:ignoredByLimit")
account-info-remote([accountId]="a") account-info-remote([accountId]="a")
button.btn.btn-xs.btn-default.ml-1((click)="removeIgnore(a._id, account._id)" title="Remove ignore") button.btn.btn-xs.btn-default.ms-1((click)="removeIgnore(a._id, account._id)" title="Remove ignore")
fa-icon([icon]="trashIcon") fa-icon([icon]="trashIcon")
a.text-muted(*ngIf="ignoredBy && ignoredBy.length > ignoredByLimit" (click)="ignoredByLimit = 9999999") a.text-muted(*ngIf="ignoredBy && ignoredBy.length > ignoredByLimit" (click)="ignoredByLimit = 9999999")
| more ... | more ...
@@ -381,7 +381,7 @@ div(*ngIf="account")
.mb-2 .mb-2
.mb-1.d-flex.align-items-center(*ngFor="let a of ignores | slice:0:ignoresLimit") .mb-1.d-flex.align-items-center(*ngFor="let a of ignores | slice:0:ignoresLimit")
account-info-remote([accountId]="a") account-info-remote([accountId]="a")
button.btn.btn-xs.btn-default.ml-1((click)="removeIgnore(account._id, a._id)" title="Remove ignore") button.btn.btn-xs.btn-default.ms-1((click)="removeIgnore(account._id, a._id)" title="Remove ignore")
fa-icon([icon]="trashIcon") fa-icon([icon]="trashIcon")
a.text-muted(*ngIf="ignores && ignores.length > ignoresLimit" (click)="ignoresLimit = 9999999") a.text-muted(*ngIf="ignores && ignores.length > ignoresLimit" (click)="ignoresLimit = 9999999")
| more ... | more ...
@@ -393,7 +393,7 @@ div(*ngIf="account")
.dropdown(dropdown) .dropdown(dropdown)
button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle)
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="addEmail()") a.dropdown-item((click)="addEmail()")
| Add email | Add email
.mb-2 .mb-2
@@ -413,7 +413,7 @@ div(*ngIf="account")
.dropdown(dropdown) .dropdown(dropdown)
button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle)
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="getPoniesCreators()") a.dropdown-item((click)="getPoniesCreators()")
| Fetch creator info | Fetch creator info
a.dropdown-item((click)="restoringPonies = true") a.dropdown-item((click)="restoringPonies = true")
@@ -425,9 +425,9 @@ div(*ngIf="account")
.mb-2(*ngIf="restoringPonies") .mb-2(*ngIf="restoringPonies")
textarea.form-control.mb-1([(ngModel)]="poniesToRestore" placeholder="paste removed pony logs here") textarea.form-control.mb-1([(ngModel)]="poniesToRestore" placeholder="paste removed pony logs here")
textarea.form-control.mb-1([(ngModel)]="poniesToRestoreFilter" placeholder="paste pony ids to use here (optional)") textarea.form-control.mb-1([(ngModel)]="poniesToRestoreFilter" placeholder="paste pony ids to use here (optional)")
.text-right .text-end
button.btn.btn-xs.btn-default((click)="poniesToRestore = ''; restoringPonies = false") cancel button.btn.btn-xs.btn-default((click)="poniesToRestore = ''; restoringPonies = false") cancel
button.btn.btn-xs.btn-success.ml-1((click)="restorePonies()" [disabled]="!poniesToRestore") restore button.btn.btn-xs.btn-success.ms-1((click)="restorePonies()" [disabled]="!poniesToRestore") restore
hr hr
.mb-2 .mb-2
pony-list-remote( pony-list-remote(
@@ -1,5 +1,5 @@
ng-template(#searchTooltip) ng-template(#searchTooltip)
.text-left.help-tooltip .text-start.help-tooltip
div: em search by: div: em search by:
div name:<account_name> #[em - account name] div name:<account_name> #[em - account name]
div note:<note_text> #[em - note contents] div note:<note_text> #[em - note contents]
@@ -20,31 +20,31 @@ ng-template(#duplicatesPopover)
.d-block.d-sm-flex .d-block.d-sm-flex
input.form-control.form-control-sm.admin-search(type="search" placeholder="search" [(ngModel)]="search") input.form-control.form-control-sm.admin-search(type="search" placeholder="search" [(ngModel)]="search")
.btn-group.btn-group-sm.ml-1 .btn-group.btn-group-sm.ms-1
button.btn.btn-default((click)="refresh(true)") button.btn.btn-default((click)="refresh(true)")
fa-icon([icon]="syncIcon" size="lg") fa-icon([icon]="syncIcon" size="lg")
button.btn(btnCheckbox [(ngModel)]="autoRefresh" [btnHighlight]="autoRefresh") button.btn(btnCheckbox [(ngModel)]="autoRefresh" [btnHighlight]="autoRefresh")
| auto | auto
.btn-group.btn-group-sm.ml-1 .btn-group.btn-group-sm.ms-1
button.btn.btn-sm.btn-danger( button.btn.btn-sm.btn-danger(
*ngIf="duplicateEntries?.length" [popover]="duplicatesPopover" [outsideClick]="true" *ngIf="duplicateEntries?.length" [popover]="duplicatesPopover" [outsideClick]="true"
placement="bottom" containerClass="popover-wide") placement="bottom" containerClass="popover-wide")
| Duplicates ({{duplicateEntries.length}}) | Duplicates ({{duplicateEntries.length}})
button.btn.btn-sm.btn-danger((click)="refreshDuplicates()" title="Refresh duplicates") button.btn.btn-sm.btn-danger((click)="refreshDuplicates()" title="Refresh duplicates")
fa-icon([icon]="syncIcon" size="lg") fa-icon([icon]="syncIcon" size="lg")
.btn-group.btn-group-sm.ml-1(btnRadioGroup [(ngModel)]="showOnly") .btn-group.btn-group-sm.ms-1(btnRadioGroup [(ngModel)]="showOnly")
button.btn(*ngFor="let f of filters" [btnRadio]="f" [btnHighlight]="showOnly === f") {{f}} button.btn(*ngFor="let f of filters" [btnRadio]="f" [btnHighlight]="showOnly === f") {{f}}
button.btn.btn-sm.ml-1((click)="not = !not" [btnHighlight]="not") not button.btn.btn-sm.ms-1((click)="not = !not" [btnHighlight]="not") not
button.btn.btn-sm.btn-default.ml-2((click)="createAccount()") create account button.btn.btn-sm.btn-default.ms-2((click)="createAccount()") create account
.d-block.d-sm-flex.justify-content-between.align-items-start .d-block.d-sm-flex.justify-content-between.align-items-start
.pl-1([tooltip]="searchTooltip" placement="bottom" containerClass="tooltip-pre" style="width: 280px;") .ps-1([tooltip]="searchTooltip" placement="bottom" containerClass="tooltip-pre" style="width: 280px;")
small.text-muted small.text-muted
fa-icon.mr-1([icon]="filterIcon") fa-icon.me-1([icon]="filterIcon")
| filters | filters
.d-block.d-sm-flex.mt-2 .d-block.d-sm-flex.mt-2
fa-icon.text-muted.mr-3(*ngIf="loading" [icon]="spinnerIcon" animation="spin" size="2x" style="margin-top: 3px") fa-icon.text-muted.me-3(*ngIf="loading" [icon]="spinnerIcon" animation="spin" size="2x" style="margin-top: 3px")
strong.text-muted.mr-3(style="margin-top: 6px") strong.text-muted.me-3(style="margin-top: 6px")
| {{totalItems === 99999999 ? '' : totalItems}} | {{totalItems === 99999999 ? '' : totalItems}}
pagination( pagination(
[totalItems]="totalItems" [itemsPerPage]="itemsPerPage" [(ngModel)]="currentPage" [totalItems]="totalItems" [itemsPerPage]="itemsPerPage" [(ngModel)]="currentPage"
@@ -7,21 +7,21 @@ ng-template(#duplicatesPopover)
input.form-control.form-control-sm.admin-search-inline.d-none.d-sm-inline-block( input.form-control.form-control-sm.admin-search-inline.d-none.d-sm-inline-block(
type="search" placeholder="search" [(ngModel)]="search" disabled) type="search" placeholder="search" [(ngModel)]="search" disabled)
button.btn.btn-sm.ml-1((click)="toggleNotifications()" [btnHighlight]="notifications" title="Toggle notifications") button.btn.btn-sm.ms-1((click)="toggleNotifications()" [btnHighlight]="notifications" title="Toggle notifications")
fa-icon([icon]="bellIcon" size="lg") fa-icon([icon]="bellIcon" size="lg")
button.btn.btn-sm.btn-default.ml-1((click)="cleanupDeleted()" title="Cleanup deleted events") button.btn.btn-sm.btn-default.ms-1((click)="cleanupDeleted()" title="Cleanup deleted events")
fa-icon.mr-1([icon]="syncIcon" size="lg") fa-icon.me-1([icon]="syncIcon" size="lg")
| clear | clear
button.btn.btn-sm.btn-default.ml-1((click)="removeEvents(1000 * 60 * 60 * 24)" title="Delete all older than 1 day") button.btn.btn-sm.btn-default.ms-1((click)="removeEvents(1000 * 60 * 60 * 24)" title="Delete all older than 1 day")
fa-icon.mr-1([icon]="clockIcon" size="lg") fa-icon.me-1([icon]="clockIcon" size="lg")
| 1day | 1day
button.btn.btn-sm.btn-default.ml-1((click)="removeEvents(1000 * 3)" title="Delete all events") button.btn.btn-sm.btn-default.ms-1((click)="removeEvents(1000 * 3)" title="Delete all events")
fa-icon.mr-1([icon]="trashIcon" size="lg") fa-icon.me-1([icon]="trashIcon" size="lg")
| all | all
button.btn.btn-sm.btn-default.ml-1((click)="showChat()" title="Show chatlog") button.btn.btn-sm.btn-default.ms-1((click)="showChat()" title="Show chatlog")
fa-icon.mr-1([icon]="commentsIcon" size="lg") fa-icon.me-1([icon]="commentsIcon" size="lg")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-sm.btn-danger( button.btn.btn-sm.btn-danger(
*ngIf="duplicateEntries?.length" [popover]="duplicatesPopover" placement="bottom" containerClass="popover-wide") *ngIf="duplicateEntries?.length" [popover]="duplicatesPopover" placement="bottom" containerClass="popover-wide")
| duplicates ({{duplicateEntries.length}}) | duplicates ({{duplicateEntries.length}})
@@ -29,14 +29,14 @@ ng-template(#duplicatesPopover)
fa-icon([icon]="syncIcon" size="lg") fa-icon([icon]="syncIcon" size="lg")
span.text-muted.d-none.d-sm-inline span.text-muted.d-none.d-sm-inline
span.ml-3(title="Used disk space" [class.text-danger]="isLowDiskSpace") span.ms-3(title="Used disk space" [class.text-danger]="isLowDiskSpace")
fa-icon.mr-2([icon]="hddIcon") fa-icon.me-2([icon]="hddIcon")
| {{status.diskSpace}} | {{status.diskSpace}}
span.ml-3(title="Memory usage" [class.text-danger]="isLowMemory") span.ms-3(title="Memory usage" [class.text-danger]="isLowMemory")
fa-icon.mr-2([icon]="ramIcon") fa-icon.me-2([icon]="ramIcon")
| {{status.memoryUsage}} | {{status.memoryUsage}}
span.ml-3(title="Certificate expires in" [class.text-danger]="isOldCertificate") span.ms-3(title="Certificate expires in" [class.text-danger]="isOldCertificate")
fa-icon.mr-2([icon]="certificateIcon") fa-icon.me-2([icon]="certificateIcon")
from-now([time]="status.certificateExpiration") from-now([time]="status.certificateExpiration")
pagination( pagination(
@@ -11,14 +11,14 @@
div div
span.text-muted created: span.text-muted created:
from-now.ml-1([time]="info.origin?.createdAt") from-now.ms-1([time]="info.origin?.createdAt")
div div
span.text-muted updated: span.text-muted updated:
from-now.ml-1([time]="info.origin?.updatedAt") from-now.ms-1([time]="info.origin?.updatedAt")
.col-md-6 .col-md-6
h3 Accounts #[span.text-muted.ml-1 ({{accounts.length}})] h3 Accounts #[span.text-muted.ms-1 ({{accounts.length}})]
div(*ngFor="let a of accounts | slice:0:50") div(*ngFor="let a of accounts | slice:0:50")
account-info-remote([accountId]="a") account-info-remote([accountId]="a")
@@ -5,7 +5,7 @@
.col-md-6 .col-md-6
h3 h3
| Origins statistics | Origins statistics
button.btn.btn-xs.btn-default.ml-1((click)="update()") button.btn.btn-xs.btn-default.ms-1((click)="update()")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.stat-field Total origin count: #[b {{stats.totalOrigins}}] .stat-field Total origin count: #[b {{stats.totalOrigins}}]
@@ -16,14 +16,14 @@
h3.mt-3 h3.mt-3
| Ignores statistics | Ignores statistics
button.btn.btn-xs.btn-default.ml-1((click)="update()") button.btn.btn-xs.btn-default.ms-1((click)="update()")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.stat-field Total ignore count: #[b {{other?.totalIgnores}}] .stat-field Total ignore count: #[b {{other?.totalIgnores}}]
h3.mt-3 h3.mt-3
| Other statistics | Other statistics
button.btn.btn-xs.btn-default.ml-1((click)="update()") button.btn.btn-xs.btn-default.ms-1((click)="update()")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.stat-field Auths with empty account: #[b {{other?.authsWithEmptyAccount}}] .stat-field Auths with empty account: #[b {{other?.authsWithEmptyAccount}}]
@@ -45,15 +45,15 @@
td td
button.btn.btn-xs.btn-default((click)="clear(i)" [disabled]="pending" title="Clear old singles in this row") button.btn.btn-xs.btn-default((click)="clear(i)" [disabled]="pending" title="Clear old singles in this row")
fa-icon([icon]="eraserIcon" [fixedWidth]="true") fa-icon([icon]="eraserIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1((click)="clear(i, true)" [disabled]="pending" title="Clear old singles in or below this row") button.btn.btn-xs.btn-default.ms-1((click)="clear(i, true)" [disabled]="pending" title="Clear old singles in or below this row")
fa-icon([icon]="eraserIcon" [fixedWidth]="true") fa-icon([icon]="eraserIcon" [fixedWidth]="true")
fa-icon([icon]="chevronDownIcon" [fixedWidth]="true") fa-icon([icon]="chevronDownIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1((click)="clearSingles(i)" [disabled]="pending" title="Clear singles in or below this row") button.btn.btn-xs.btn-default.ms-1((click)="clearSingles(i)" [disabled]="pending" title="Clear singles in or below this row")
fa-icon([icon]="userIcon" [fixedWidth]="true") fa-icon([icon]="userIcon" [fixedWidth]="true")
fa-icon([icon]="chevronDownIcon" [fixedWidth]="true") fa-icon([icon]="chevronDownIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1((click)="clearOld(i)" [disabled]="pending" title="Clear very old (3 months) in or below this row") button.btn.btn-xs.btn-default.ms-1((click)="clearOld(i)" [disabled]="pending" title="Clear very old (3 months) in or below this row")
fa-icon([icon]="clockIcon" [fixedWidth]="true") fa-icon([icon]="clockIcon" [fixedWidth]="true")
fa-icon([icon]="chevronDownIcon" [fixedWidth]="true") fa-icon([icon]="chevronDownIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1((click)="clearTo10(i)" [disabled]="pending" title="Trim origins to 10 most recent") button.btn.btn-xs.btn-default.ms-1((click)="clearTo10(i)" [disabled]="pending" title="Trim origins to 10 most recent")
b 10 b 10
fa-icon([icon]="chevronDownIcon" [fixedWidth]="true") fa-icon([icon]="chevronDownIcon" [fixedWidth]="true")
@@ -10,7 +10,7 @@
textarea.form-control([(ngModel)]="field.value" rows="4" style="width: 400px;") textarea.form-control([(ngModel)]="field.value" rows="4" style="width: 400px;")
.form-group .form-group
button.btn.btn-primary(type="button" (click)="saveFields()") Save button.btn.btn-primary(type="button" (click)="saveFields()") Save
button.btn.btn-default.ml-1(type="button" (click)="resetFields()") Reset button.btn.btn-default.ms-1(type="button" (click)="resetFields()") Reset
.col-6 .col-6
h2.text-danger PATREON WARNING: h2.text-danger PATREON WARNING:
@@ -34,4 +34,4 @@
| {{suspiciousPoniesError}} | {{suspiciousPoniesError}}
.form-group .form-group
button.btn.btn-primary((click)="saveSuspiciousPonies()") Save button.btn.btn-primary((click)="saveSuspiciousPonies()") Save
button.btn.btn-default.ml-1((click)="resetSuspiciousPonies()") Reset button.btn.btn-default.ms-1((click)="resetSuspiciousPonies()") Reset
@@ -1,12 +1,12 @@
ng-template(#searchTooltip) ng-template(#searchTooltip)
.text-left.help-tooltip .text-start.help-tooltip
div: em search by: div: em search by:
div exact:<name> #[em - exact pony name] div exact:<name> #[em - exact pony name]
div orphan #[em - list orphaned ponies] div orphan #[em - list orphaned ponies]
.form-horizontal .form-horizontal
input.form-control.form-control-sm.admin-search(type="search" placeholder="search" [(ngModel)]="search") input.form-control.form-control-sm.admin-search(type="search" placeholder="search" [(ngModel)]="search")
.btn-group.btn-group-sm.ml-1 .btn-group.btn-group-sm.ms-1
button.btn.btn-default((click)="refresh()") button.btn.btn-default((click)="refresh()")
fa-icon([icon]="syncIcon" size="lg") fa-icon([icon]="syncIcon" size="lg")
@@ -18,16 +18,16 @@ ng-template(#searchTooltip)
button.btn(btnRadio="-lastUsed" [btnHighlight]="orderBy === '-lastUsed'") button.btn(btnRadio="-lastUsed" [btnHighlight]="orderBy === '-lastUsed'")
| last used | last used
.pl-1([tooltip]="searchTooltip" placement="bottom" containerClass="tooltip-pre" style="width: 280px;") .ps-1([tooltip]="searchTooltip" placement="bottom" containerClass="tooltip-pre" style="width: 280px;")
small.text-muted small.text-muted
fa-icon.mr-1([icon]="filterIcon") fa-icon.me-1([icon]="filterIcon")
| filters | filters
.d-block.d-sm-flex.justify-content-end .d-block.d-sm-flex.justify-content-end
.table-loader.text-muted.flex-grow-1.text-left(*ngIf="loading") .table-loader.text-muted.flex-grow-1.text-start(*ngIf="loading")
fa-icon.mr-1([icon]="spinnerIcon" animation="spin") fa-icon.me-1([icon]="spinnerIcon" animation="spin")
| Loading... | Loading...
strong.text-muted.mr-3(style="margin-top: 6px") strong.text-muted.me-3(style="margin-top: 6px")
| {{totalItems > 900000000 ? '---' : totalItems}} | {{totalItems > 900000000 ? '---' : totalItems}}
pagination( pagination(
[totalItems]="totalItems" [itemsPerPage]="itemsPerPage" [(ngModel)]="currentPage" [maxSize]="15" [totalItems]="totalItems" [itemsPerPage]="itemsPerPage" [(ngModel)]="currentPage" [maxSize]="15"
@@ -56,7 +56,7 @@ table.table.table-fixed.table-striped.table-hover.table-sm
td(style="width: 80px;") td(style="width: 80px;")
button.btn.btn-xs.btn-danger((click)="remove(i)" title="Remove pony") button.btn.btn-xs.btn-danger((click)="remove(i)" title="Remove pony")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-default.ml-1( button.btn.btn-xs.btn-default.ms-1(
(click)="$event.shiftKey ? chatLog.add(accountInfo.account) : chatLog.show(accountInfo.account)" title="Show chat") (click)="$event.shiftKey ? chatLog.add(accountInfo.account) : chatLog.show(accountInfo.account)" title="Show chat")
fa-icon([icon]="commentIcon" [fixedWidth]="true") fa-icon([icon]="commentIcon" [fixedWidth]="true")
@@ -8,16 +8,16 @@ div(style="position: relative;")
| Fit zoom | Fit zoom
button.btn.btn-default((click)="fullFrameZoom()") button.btn.btn-default((click)="fullFrameZoom()")
| Full frame | Full frame
button.btn.btn-default.ml-1(*ngIf="loaded" (click)="load(server)") button.btn.btn-default.ms-1(*ngIf="loaded" (click)="load(server)")
| Refresh | Refresh
button.btn.btn-default.ml-1(*ngIf="loaded" (click)="disable()") button.btn.btn-default.ms-1(*ngIf="loaded" (click)="disable()")
| Disable | Disable
button.btn.btn-default.ml-1(*ngIf="!loaded && server" (click)="enable()") button.btn.btn-default.ms-1(*ngIf="!loaded && server" (click)="enable()")
| Enable | Enable
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
| Select | Select
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
button.dropdown-item(*ngFor="let s of servers" (click)="load(s)") button.dropdown-item(*ngFor="let s of servers" (click)="load(s)")
| {{s}} | {{s}}
@@ -26,97 +26,97 @@ div(style="position: relative;")
div(#tooltip style="display: none; position: absolute; left: 0; top: 0; padding: 2px 6px; background: #111; border-radius: 2px; font-size: 12px; white-space: pre; pointer-events: none;") div(#tooltip style="display: none; position: absolute; left: 0; top: 0; padding: 2px 6px; background: #111; border-radius: 2px; font-size: 12px; white-space: pre; pointer-events: none;")
p p
.float-right.text-muted .float-end.text-muted
div samples: {{timings.length}} div samples: {{timings.length}}
br br
.float-right.text-muted .float-end.text-muted
div sampling: {{worldPerfStats.isSamplingEnabled}} div sampling: {{worldPerfStats.isSamplingEnabled}}
br br
.float-right.text-muted .float-end.text-muted
div avg update: {{worldPerfStats.avgUpdateTime.toFixed(2)}} div avg update: {{worldPerfStats.avgUpdateTime.toFixed(2)}}
br br
.float-right.text-muted .float-end.text-muted
div last update: {{worldPerfStats.lastUpdateTime.toFixed(2)}} div last update: {{worldPerfStats.lastUpdateTime.toFixed(2)}}
br br
.float-right.text-muted .float-end.text-muted
div max update: {{worldPerfStats.maxUpdateTime.toFixed(2)}} div max update: {{worldPerfStats.maxUpdateTime.toFixed(2)}}
br br
.float-right.text-muted .float-end.text-muted
div min update: {{worldPerfStats.minUpdateTime.toFixed(2)}} div min update: {{worldPerfStats.minUpdateTime.toFixed(2)}}
br br
.float-right.text-muted .float-end.text-muted
div moving entities: {{worldPerfStats.movingEntities}} div moving entities: {{worldPerfStats.movingEntities}}
br br
.float-right.text-muted .float-end.text-muted
div controllers: {{worldPerfStats.controllersCount}} div controllers: {{worldPerfStats.controllersCount}}
br br
.float-right.text-muted .float-end.text-muted
div regions: {{worldPerfStats.regionsCount}} div regions: {{worldPerfStats.regionsCount}}
br br
.float-right.text-muted .float-end.text-muted
div maps: {{worldPerfStats.mapsCount}} div maps: {{worldPerfStats.mapsCount}}
br br
.float-right.text-muted .float-end.text-muted
div clients: {{worldPerfStats.clients}} div clients: {{worldPerfStats.clients}}
br br
.float-right.text-muted .float-end.text-muted
div clients with adds: {{worldPerfStats.clientsWithAdds}} div clients with adds: {{worldPerfStats.clientsWithAdds}}
br br
.float-right.text-muted .float-end.text-muted
div clients with updates: {{worldPerfStats.clientsWithUpdates}} div clients with updates: {{worldPerfStats.clientsWithUpdates}}
br br
.float-right.text-muted .float-end.text-muted
div clients with says: {{worldPerfStats.clientsWithSays}} div clients with says: {{worldPerfStats.clientsWithSays}}
br br
.float-right.text-muted .float-end.text-muted
div total says: {{worldPerfStats.totalSays}} div total says: {{worldPerfStats.totalSays}}
br br
.float-right.text-muted .float-end.text-muted
div client queue: {{worldPerfStats.clientQueue}} div client queue: {{worldPerfStats.clientQueue}}
br br
.float-right.text-muted .float-end.text-muted
div client sent: {{(worldPerfStats.sent / 1024).toFixed(2) + 'kb'}} div client sent: {{(worldPerfStats.sent / 1024).toFixed(2) + 'kb'}}
br br
.float-right.text-muted .float-end.text-muted
div client received: {{(worldPerfStats.received / 1024).toFixed(2) + 'kb'}} div client received: {{(worldPerfStats.received / 1024).toFixed(2) + 'kb'}}
br br
.float-right.text-muted .float-end.text-muted
div client sent packets: {{worldPerfStats.sentPackets}} div client sent packets: {{worldPerfStats.sentPackets}}
br br
.float-right.text-muted .float-end.text-muted
div client received packets: {{worldPerfStats.receivedPackets}} div client received packets: {{worldPerfStats.receivedPackets}}
table.table.table-sm(style="position: relative; bottom : 410px; font-size: small; width: 1000px;") table.table.table-sm(style="position: relative; bottom : 410px; font-size: small; width: 1000px;")
thead thead
tr tr
th.text-right Self Time th.text-end Self Time
th.text-right Self % th.text-end Self %
th.text-right Total % th.text-end Total %
th.text-right Count th.text-end Count
th Name th Name
tbody.font-monospace tbody.font-monospace
tr(*ngFor="let l of listing") tr(*ngFor="let l of listing")
td.text-right {{l.selfTime.toFixed(2)}} ms td.text-end {{l.selfTime.toFixed(2)}} ms
td.text-right.text-muted {{l.selfPercent.toFixed(2)}} % td.text-end.text-muted {{l.selfPercent.toFixed(2)}} %
td.text-right.text-muted {{l.totalPercent.toFixed(2)}} % td.text-end.text-muted {{l.totalPercent.toFixed(2)}} %
td.text-right.text-muted {{l.count}} td.text-end.text-muted {{l.count}}
td {{l.name}} td {{l.name}}
@@ -1,9 +1,9 @@
div(*ngIf="isSuperadmin") div(*ngIf="isSuperadmin")
button.btn.btn-sm.btn-default((click)="notifyOfUpdate()") button.btn.btn-sm.btn-default((click)="notifyOfUpdate()")
| Notify of update | Notify of update
button.btn.btn-sm.btn-default.ml-1((click)="shutdownServers()") button.btn.btn-sm.btn-default.ms-1((click)="shutdownServers()")
| Shutdown servers | Shutdown servers
button.btn.btn-sm.btn-default.ml-1((click)="resetUpdating()") button.btn.btn-sm.btn-default.ms-1((click)="resetUpdating()")
| Reset updating | Reset updating
h3.mt-4 Servers h3.mt-4 Servers
@@ -16,18 +16,18 @@ h3.mt-4 Servers
.badge.badge-none(*ngIf="s.dead") dead .badge.badge-none(*ngIf="s.dead") dead
.badge.badge-success(*ngIf="!s.dead && !s.isPageOffline") online .badge.badge-success(*ngIf="!s.dead && !s.isPageOffline") online
.badge.badge-danger(*ngIf="!s.dead && s.isPageOffline") offline .badge.badge-danger(*ngIf="!s.dead && s.isPageOffline") offline
.badge.badge-warning.ml-1(*ngIf="s.updating") updating .badge.badge-warning.ms-1(*ngIf="s.updating") updating
.col-md-6 .col-md-6
button.btn.btn-sm.btn-success((click)="updateLoginSettings({ isPageOffline: false })") button.btn.btn-sm.btn-success((click)="updateLoginSettings({ isPageOffline: false })")
| Switch online | Switch online
button.btn.btn-sm.btn-danger.ml-1((click)="updateLoginSettings({ isPageOffline: true })") button.btn.btn-sm.btn-danger.ms-1((click)="updateLoginSettings({ isPageOffline: true })")
| Switch offline | Switch offline
button.btn.btn-sm.btn-default.ml-1((click)="fetchRequestStats()" title="Show request stats from last hour") button.btn.btn-sm.btn-default.ms-1((click)="fetchRequestStats()" title="Show request stats from last hour")
| Stats | Stats
.row.form-group .row.form-group
.col-md-3 .col-md-3
.col-md-9 .col-md-9
.text-left(style="column-width: 280px;") .text-start(style="column-width: 280px;")
div(*ngFor="let o of loginOptions") div(*ngFor="let o of loginOptions")
on-off-switch([on]="s[o.id]" (toggle)="updateLoginSetting(o.id, $event)" [label]="o.label") on-off-switch([on]="s[o.id]" (toggle)="updateLoginSetting(o.id, $event)" [label]="o.label")
@@ -41,7 +41,7 @@ h3.mt-4 Servers
th count th count
th avg th avg
th th
button.float-right.btn.btn-default.btn-xs((click)="resetRequestStats()") close button.float-end.btn.btn-default.btn-xs((click)="resetRequestStats()") close
| total | total
tbody tbody
tr(*ngFor="let s of requestStats") tr(*ngFor="let s of requestStats")
@@ -69,26 +69,26 @@ h3.mt-4 Servers
strong {{s.name}} strong {{s.name}}
.col-md-2 .col-md-2
div div
strong.mr-1 {{s.online}} strong.me-1 {{s.online}}
span.text-muted users span.text-muted users
span.text-muted.ml-2(title="Users in queue | on main map") ({{s.queued}} | {{s.onMain}}) span.text-muted.ms-2(title="Users in queue | on main map") ({{s.queued}} | {{s.onMain}})
strong.mr-1.ml-2 {{s.maps}} strong.me-1.ms-2 {{s.maps}}
span.text-muted maps span.text-muted maps
.col-md-2.pb-1 .col-md-2.pb-1
.badge.badge-none(*ngIf="s.dead") dead .badge.badge-none(*ngIf="s.dead") dead
.badge.badge-danger(*ngIf="!s.dead && s.settings.isServerOffline") offline .badge.badge-danger(*ngIf="!s.dead && s.settings.isServerOffline") offline
.badge.badge-success(*ngIf="!s.dead && !s.settings.isServerOffline") online .badge.badge-success(*ngIf="!s.dead && !s.settings.isServerOffline") online
.badge.badge-forbidden.ml-1(*ngIf="s.require") {{s.require}} .badge.badge-forbidden.ms-1(*ngIf="s.require") {{s.require}}
.badge.badge-warning.ml-1(*ngIf="s.shutdown") shutdown .badge.badge-warning.ms-1(*ngIf="s.shutdown") shutdown
.col-md-6 .col-md-6
.d-flex .d-flex
button.btn.btn-sm.btn-success((click)="updateServerSettings(s, { isServerOffline: false })" [disabled]="s.dead") button.btn.btn-sm.btn-success((click)="updateServerSettings(s, { isServerOffline: false })" [disabled]="s.dead")
| Switch online | Switch online
button.btn.btn-sm.btn-danger.ml-1((click)="updateServerSettings(s, { isServerOffline: true })" [disabled]="s.dead") button.btn.btn-sm.btn-danger.ms-1((click)="updateServerSettings(s, { isServerOffline: true })" [disabled]="s.dead")
| Switch offline | Switch offline
button.btn.btn-sm.btn-danger.ml-1((click)="kickAll(s)" [disabled]="s.dead") button.btn.btn-sm.btn-danger.ms-1((click)="kickAll(s)" [disabled]="s.dead")
| Kick all | Kick all
.dropdown.ml-1.d-flex(dropdown) .dropdown.ms-1.d-flex(dropdown)
button.dropdown-toggle.btn.btn-sm.btn-default(dropdownToggle [disabled]="s.dead") button.dropdown-toggle.btn.btn-sm.btn-default(dropdownToggle [disabled]="s.dead")
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -106,17 +106,17 @@ h3.mt-4 Servers
| Shutdown server | Shutdown server
button.dropdown-item.btn.btn-sm.btn-default((click)="resetUpdating(s.id)") button.dropdown-item.btn.btn-sm.btn-default((click)="resetUpdating(s.id)")
| Reset updating | Reset updating
button.btn.btn-sm.btn-default.ml-1( button.btn.btn-sm.btn-default.ms-1(
(click)="showSettings[s.id] = !showSettings[s.id]" [class.active]="showSettings[s.id]" (click)="showSettings[s.id] = !showSettings[s.id]" [class.active]="showSettings[s.id]"
[disabled]="s.dead" title="Settings") [disabled]="s.dead" title="Settings")
fa-icon([icon]="optionsIcon") fa-icon([icon]="optionsIcon")
.row.form-group(*ngIf="s.settings && !s.dead") .row.form-group(*ngIf="s.settings && !s.dead")
.col-md-3.pb-1 .col-md-3.pb-1
.badge.badge-none.mr-1(*ngFor="let f of s.flags | keys") .badge.badge-none.me-1(*ngFor="let f of s.flags | keys")
| {{f}} | {{f}}
.col-md-9(*ngIf="showSettings[s.id]") .col-md-9(*ngIf="showSettings[s.id]")
.text-left(style="column-width: 280px;") .text-start(style="column-width: 280px;")
div(*ngFor="let o of options") div(*ngFor="let o of options")
on-off-switch( on-off-switch(
[on]="s.settings[o.id]" (toggle)="updateServerSetting(s, o.id, $event)" [disabled]="s.dead" [label]="o.label") [on]="s.settings[o.id]" (toggle)="updateServerSetting(s, o.id, $event)" [disabled]="s.dead" [label]="o.label")
@@ -133,7 +133,7 @@ h3.mt-4 Servers
th count (str) th count (str)
th average th average
th th
button.float-right.btn.btn-default.btn-xs((click)="resetStats(s)") close button.float-end.btn.btn-default.btn-xs((click)="resetStats(s)") close
| total | total
tbody tbody
tr(*ngFor="let a of stats.actions") tr(*ngFor="let a of stats.actions")
@@ -152,7 +152,7 @@ h3.mt-4 Servers
tr tr
th(*ngFor="let cell of stats[0]") {{cell}} th(*ngFor="let cell of stats[0]") {{cell}}
th th
button.float-right.btn.btn-default.btn-xs((click)="resetStatsTable(s)") close button.float-end.btn.btn-default.btn-xs((click)="resetStatsTable(s)") close
| |
tbody tbody
tr(*ngFor="let row of stats | slice:1") tr(*ngFor="let row of stats | slice:1")
+2 -2
View File
@@ -3,7 +3,7 @@
.d-flex.justify-content-between .d-flex.justify-content-between
.admin-initializing .admin-initializing
div(*ngIf="loading") div(*ngIf="loading")
fa-icon.mr-1([icon]="spinnerIcon" animation="spin") fa-icon.me-1([icon]="spinnerIcon" animation="spin")
| {{loading}}... | {{loading}}...
menu-bar([loading]="model.loading" [account]="model.account" (signOut)="signOut()") menu-bar([loading]="model.loading" [account]="model.account" (signOut)="signOut()")
@@ -20,5 +20,5 @@
.admin-error(*ngIf="model.error") .admin-error(*ngIf="model.error")
.alert.alert-danger .alert.alert-danger
button.close.ml-2((click)="model.error = null") × button.close.ms-2((click)="model.error = null") ×
| {{model.error}} | {{model.error}}
@@ -11,10 +11,10 @@ ng-template(#noteTooltip)
div {{account.note}} div {{account.note}}
ng-template(#alertTooltip) ng-template(#alertTooltip)
.text-left .text-start
small.text-muted small.text-muted
| expires in | expires in
from-now.ml-1([time]="alert.expires") from-now.ms-1([time]="alert.expires")
div {{alert.message}} div {{alert.message}}
ng-template(#supporterTooltip) ng-template(#supporterTooltip)
@@ -23,18 +23,18 @@ ng-template(#supporterTooltip)
| declined: #[from-now([time]="declined")] ago | {{declined | date:'MMM d'}} | declined: #[from-now([time]="declined")] ago | {{declined | date:'MMM d'}}
ng-template(#flagsTooltip) ng-template(#flagsTooltip)
.text-left .text-start
div(*ngFor="let c of counters") div(*ngFor="let c of counters")
span.text-muted.mr-1 {{c.label}}: span.text-muted.me-1 {{c.label}}:
span {{getCounter(c.name)}} span {{getCounter(c.name)}}
br(*ngIf="account.flags || account.supporter") br(*ngIf="account.flags || account.supporter")
div(*ngFor="let f of flags") div(*ngFor="let f of flags")
span(*ngIf="hasFlag(f.value)") span(*ngIf="hasFlag(f.value)")
fa-icon.mr-1([icon]="checkIcon") fa-icon.me-1([icon]="checkIcon")
| {{f.label}} | {{f.label}}
div(*ngFor="let f of supporterFlags") div(*ngFor="let f of supporterFlags")
span(*ngIf="hasSupporterFlag(f.value)") span(*ngIf="hasSupporterFlag(f.value)")
fa-icon.mr-1([icon]="checkIcon") fa-icon.me-1([icon]="checkIcon")
| {{f.label}} | {{f.label}}
ng-template(#alertModal) ng-template(#alertModal)
@@ -44,35 +44,35 @@ ng-template(#alertModal)
.modal-body.modal-checkboxes .modal-body.modal-checkboxes
.form-group .form-group
label Predefined: label Predefined:
.btn-group.ml-2 .btn-group.ms-2
button.btn.btn-sm.btn-default(*ngFor="let a of predefinedAlerts" (click)="alertMessage = a.message") button.btn.btn-sm.btn-default(*ngFor="let a of predefinedAlerts" (click)="alertMessage = a.message")
| {{a.name}} | {{a.name}}
.form-group .form-group
textarea.form-control([(ngModel)]="alertMessage" autofocus rows="4") textarea.form-control([(ngModel)]="alertMessage" autofocus rows="4")
.form-group .form-group
label Expire in label Expire in
.btn-group.ml-2(btnRadioGroup [(ngModel)]="alertExpire") .btn-group.ms-2(btnRadioGroup [(ngModel)]="alertExpire")
button.btn.btn-sm.btn-default(*ngFor="let e of alertExpires" [btnRadio]="e" [btnHighlight]="alertExpire === e") button.btn.btn-sm.btn-default(*ngFor="let e of alertExpires" [btnRadio]="e" [btnHighlight]="alertExpire === e")
| {{e.name}} | {{e.name}}
.modal-footer.d-flex .modal-footer.d-flex
.flex-grow-1 .flex-grow-1
button.btn.btn-outline-secondary((click)="cancelAlert()") button.btn.btn-outline-secondary((click)="cancelAlert()")
| Cancel | Cancel
button.btn.btn-outline-secondary.ml-2((click)="confirmAlert()") button.btn.btn-outline-secondary.ms-2((click)="confirmAlert()")
| Set | Set
//- component //- component
.account-info(*ngIf="account" [class.outdated]="isInactive") .account-info(*ngIf="account" [class.outdated]="isInactive")
span.badge.badge-admin.badge-duplicates.mr-1( span.badge.badge-admin.badge-duplicates.me-1(
*ngIf="showDuplicates && duplicates" title="Duplicates" [class.none]="duplicates.count === 0") *ngIf="showDuplicates && duplicates" title="Duplicates" [class.none]="duplicates.count === 0")
| {{duplicates.count}} | {{duplicates.count}}
fa-icon.ml-1(*ngIf="duplicates.browserId" [icon]="duplicateBrowserIdIcon") fa-icon.ms-1(*ngIf="duplicates.browserId" [icon]="duplicateBrowserIdIcon")
fa-icon.ml-1(*ngIf="duplicates.emails" [icon]="duplicateEmailIcon") fa-icon.ms-1(*ngIf="duplicates.emails" [icon]="duplicateEmailIcon")
fa-icon.ml-1(*ngIf="duplicates.name" [icon]="duplicateNameIcon") fa-icon.ms-1(*ngIf="duplicates.name" [icon]="duplicateNameIcon")
fa-icon.ml-1(*ngIf="duplicates.perma" [icon]="duplicatePermaIcon") fa-icon.ms-1(*ngIf="duplicates.perma" [icon]="duplicatePermaIcon")
a.account-info-name.mr-1( a.account-info-name.me-1(
[routerLink]="['/accounts', account._id]" [routerLink]="['/accounts', account._id]"
[tooltip]="accountTooltip" [tooltip]="accountTooltip"
[placement]="popoverPlacement || 'top'" [placement]="popoverPlacement || 'top'"
@@ -111,18 +111,18 @@ ng-template(#alertModal)
span.dropdown(dropdown autoClose="outsideClick") span.dropdown(dropdown autoClose="outsideClick")
a.icon-button.cursor-pointer.dropdown-toggle.no-arrow(dropdownToggle [tooltip]="flagsTooltip") a.icon-button.cursor-pointer.dropdown-toggle.no-arrow(dropdownToggle [tooltip]="flagsTooltip")
fa-icon([icon]="flagIcon" [fixedWidth]="true" [ngClass]="flagClass") fa-icon([icon]="flagIcon" [fixedWidth]="true" [ngClass]="flagClass")
.dropdown-menu(*dropdownMenu [class.dropdown-menu-right]="!popoverPlacement") .dropdown-menu(*dropdownMenu [class.dropdown-menu-end]="!popoverPlacement")
a.dropdown-item(*ngFor="let f of flags" (click)="toggleFlag(f.value)") a.dropdown-item(*ngFor="let f of flags" (click)="toggleFlag(f.value)")
fa-icon.mr-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasFlag(f.value)") fa-icon.me-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasFlag(f.value)")
| {{f.label}} | {{f.label}}
.dropdown-divider .dropdown-divider
a.dropdown-item(*ngFor="let f of supporterFlags" (click)="toggleSupporterFlag(f.value)") a.dropdown-item(*ngFor="let f of supporterFlags" (click)="toggleSupporterFlag(f.value)")
fa-icon.mr-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasSupporterFlag(f.value)") fa-icon.me-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasSupporterFlag(f.value)")
| {{f.label}} | {{f.label}}
.dropdown-item .dropdown-item
.d-flex.justify-content-between .d-flex.justify-content-between
div div
fa-icon.mr-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasAnySupporter") fa-icon.me-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasAnySupporter")
| supporter | supporter
.btn-group.supporter-buttons .btn-group.supporter-buttons
button.btn.btn-xs.btn-info([class.active]="isSupporter(0)" (click)="setSupporter(0)") none button.btn.btn-xs.btn-info([class.active]="isSupporter(0)" (click)="setSupporter(0)") none
@@ -132,7 +132,7 @@ ng-template(#alertModal)
.dropdown-item .dropdown-item
.d-flex.justify-content-between .d-flex.justify-content-between
div div
fa-icon.mr-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasPastSupporter") fa-icon.me-1([icon]="checkIcon" [fixedWidth]="true" [class.invisible]="!hasPastSupporter")
| past supporter | past supporter
.btn-group.supporter-buttons .btn-group.supporter-buttons
button.btn.btn-xs.btn-info([class.active]="isForcePastSupporter" (click)="toggleForcePastSupporter()") force button.btn.btn-xs.btn-info([class.active]="isForcePastSupporter" (click)="toggleForcePastSupporter()") force
@@ -149,7 +149,7 @@ ng-template(#alertModal)
span.dropdown(dropdown) span.dropdown(dropdown)
a.icon-button.cursor-pointer.dropdown-toggle.no-arrow(dropdownToggle [tooltip]="alert ? alertTooltip : undefined") a.icon-button.cursor-pointer.dropdown-toggle.no-arrow(dropdownToggle [tooltip]="alert ? alertTooltip : undefined")
fa-icon.text-muted([icon]="cogIcon" [fixedWidth]="true" [class.text-present]="alert") fa-icon.text-muted([icon]="cogIcon" [fixedWidth]="true" [class.text-present]="alert")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="kick()") a.dropdown-item((click)="kick()")
| kick | kick
a.dropdown-item((click)="report()") a.dropdown-item((click)="report()")
@@ -4,7 +4,7 @@
| offline | offline
.text-safe(*ngFor="let s of status") .text-safe(*ngFor="let s of status")
| [{{s.server}}] [{{s.map}}] {{s.character}} ({{s.x}}, {{s.y}}) ({{s.duration}}) | [{{s.server}}] [{{s.map}}] {{s.character}} ({{s.x}}, {{s.y}}) ({{s.duration}})
ua-info.ml-1([userAgent]="s.userAgent") ua-info.ms-1([userAgent]="s.userAgent")
fa-icon.ml-1(*ngIf="s.incognito" [icon]="incognitoIcon") fa-icon.ms-1(*ngIf="s.incognito" [icon]="incognitoIcon")
.text-muted(*ngIf="verbose") .text-muted(*ngIf="verbose")
small {{s.userAgent}} small {{s.userAgent}}
@@ -1,7 +1,7 @@
.text-left .text-start
div div
| {{account.name || '[none]'}} [{{account._id | slice:-3}}] | {{account.name || '[none]'}} [{{account._id | slice:-3}}]
auth-list-remote.ml-1(*ngIf="!extendedAuths" [accountId]="account._id") auth-list-remote.ms-1(*ngIf="!extendedAuths" [accountId]="account._id")
.text-muted .text-muted
em {{account.name | translit}} em {{account.name | translit}}
div(*ngIf="extendedAuths") div(*ngIf="extendedAuths")
@@ -12,16 +12,16 @@
| ({{account.emails.length - 3}} more) | ({{account.emails.length - 3}} more)
div div
span.text-muted created: span.text-muted created:
from-now.ml-1([time]="account.createdAt") from-now.ms-1([time]="account.createdAt")
div div
span.text-muted last visit: span.text-muted last visit:
from-now.ml-1([time]="account.lastVisit") from-now.ms-1([time]="account.lastVisit")
div div
span.text-muted ponies: span.text-muted ponies:
span.ml-1 {{account.characterCount}} span.ms-1 {{account.characterCount}}
div div
span.text-muted age: span.text-muted age:
span.ml-1([class.text-strike]="account.birthyear") {{age}} span.ms-1([class.text-strike]="account.birthyear") {{age}}
span.ml-1 {{forceAge}} span.ms-1 {{forceAge}}
div div
account-status([account]="account") account-status([account]="account")
@@ -2,37 +2,37 @@ div(*ngIf="open || !canClose")
.d-flex.justify-content-between.align-items-center .d-flex.justify-content-between.align-items-center
h3 h3
| {{title}} | {{title}}
span.text-muted.ml-1 span.text-muted.ms-1
| ({{date ? date.label : 'none'}}) | ({{date ? date.label : 'none'}})
span.text-muted.ml-1(*ngIf="loading") span.text-muted.ms-1(*ngIf="loading")
fa-icon([icon]="spinnerIcon" animation="spin") fa-icon([icon]="spinnerIcon" animation="spin")
.form-inline .form-inline
ng-content ng-content
form.d-inline-block((submit)="searchChat(searchInput.value)") form.d-inline-block((submit)="searchChat(searchInput.value)")
input.form-control.form-control-sm.ml-1(#searchInput type="search" placeholder="search") input.form-control.form-control-sm.ms-1(#searchInput type="search" placeholder="search")
button.btn.btn-sm.btn-default.ml-1(type="submit" title="Search whole chat for phrase") button.btn.btn-sm.btn-default.ms-1(type="submit" title="Search whole chat for phrase")
fa-icon([icon]="searchIcon" [fixedWidth]="true" size="lg") fa-icon([icon]="searchIcon" [fixedWidth]="true" size="lg")
button.btn.btn-sm.btn-default.ml-1((click)="openLog()" title="Open log in plain text format") button.btn.btn-sm.btn-default.ms-1((click)="openLog()" title="Open log in plain text format")
fa-icon([icon]="fileIcon" [fixedWidth]="true" size="lg") fa-icon([icon]="fileIcon" [fixedWidth]="true" size="lg")
button.btn.btn-sm.ml-1( button.btn.btn-sm.ms-1(
[(ngModel)]="autoRefresh" btnCheckbox [btnHighlight]="autoRefresh" title="Auto-refresh every 10 seconds") [(ngModel)]="autoRefresh" btnCheckbox [btnHighlight]="autoRefresh" title="Auto-refresh every 10 seconds")
fa-icon.mr-1([icon]="syncIcon" [fixedWidth]="true" size="lg") fa-icon.me-1([icon]="syncIcon" [fixedWidth]="true" size="lg")
| auto | auto
.btn-group.btn-group-sm.ml-1 .btn-group.btn-group-sm.ms-1
button.btn.btn-sm.btn-default((click)="prev()" title="Load previous day") button.btn.btn-sm.btn-default((click)="prev()" title="Load previous day")
fa-icon([icon]="chevronLeftIcon" [fixedWidth]="true" size="lg") fa-icon([icon]="chevronLeftIcon" [fixedWidth]="true" size="lg")
button.btn.btn-sm.btn-default((click)="next()" title="Load next day") button.btn.btn-sm.btn-default((click)="next()" title="Load next day")
fa-icon([icon]="chevronRightIcon" [fixedWidth]="true" size="lg") fa-icon([icon]="chevronRightIcon" [fixedWidth]="true" size="lg")
.btn-group.btn-group-sm.dropup.ml-1(dropdown) .btn-group.btn-group-sm.dropup.ms-1(dropdown)
button.btn.btn-sm.btn-default((click)="showDate(today)") button.btn.btn-sm.btn-default((click)="showDate(today)")
| Load todays chat | Load todays chat
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item(*ngFor="let d of dates" (click)="showDate(d)") a.dropdown-item(*ngFor="let d of dates" (click)="showDate(d)")
| {{d.label}} | {{d.label}}
button.btn.btn-sm.btn-default.ml-1(*ngIf="canClose" (click)="close()") button.btn.btn-sm.btn-default.ms-1(*ngIf="canClose" (click)="close()")
fa-icon([icon]="closeIcon" [fixedWidth]="true") fa-icon([icon]="closeIcon" [fixedWidth]="true")
.mb-1(*ngIf="accounts.length") .mb-1(*ngIf="accounts.length")
a.badge.badge-none.mr-1(*ngFor="let a of accounts; let i = index" (click)="removeAccount(i)" title="Remove") a.badge.badge-none.me-1(*ngFor="let a of accounts; let i = index" (click)="removeAccount(i)" title="Remove")
| [{{i + 1}}] {{a.name}} | [{{i + 1}}] {{a.name}}
.well.pre.chatlog .well.pre.chatlog
@@ -1,15 +1,15 @@
.d-flex.align-items-center.mb-1 .d-flex.align-items-center.mb-1
auth-info.flex-grow-1([auth]="auth" [showName]="true") auth-info.flex-grow-1([auth]="auth" [showName]="true")
small.text-muted small.text-muted
from-now.mr-1([time]="auth?.lastUsed") from-now.me-1([time]="auth?.lastUsed")
.btn-group.dropdown(dropdown) .btn-group.dropdown(dropdown)
button.btn.btn-xs.btn-default(dropdownToggle title="Assign to another account") button.btn.btn-xs.btn-default(dropdownToggle title="Assign to another account")
fa-icon([icon]="assignIcon" [fixedWidth]="true") fa-icon([icon]="assignIcon" [fixedWidth]="true")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item(*ngFor="let d of duplicates" (click)="assignTo(d.account)") button.dropdown-item(*ngFor="let d of duplicates" (click)="assignTo(d.account)")
span.text-muted assign to span.text-muted assign to
account-info-remote.ml-1([accountId]="d.account" [basic]="true") account-info-remote.ms-1([accountId]="d.account" [basic]="true")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-xs.btn-default((click)="showAuthData(auth)" title="Show more data") button.btn.btn-xs.btn-default((click)="showAuthData(auth)" title="Show more data")
fa-icon([icon]="infoIcon" [fixedWidth]="true") fa-icon([icon]="infoIcon" [fixedWidth]="true")
button.btn.btn-xs((click)="toggleAuthBanned(auth)" [btnHighlight]="auth?.banned || false" button.btn.btn-xs((click)="toggleAuthBanned(auth)" [btnHighlight]="auth?.banned || false"
@@ -3,11 +3,11 @@ a(*ngIf="auth?.url" [href]="auth?.url" target="_blank" rel="noopener noreferrer"
span(*ngIf="!auth?.url" [title]="name") span(*ngIf="!auth?.url" [title]="name")
fa-icon([icon]="icon" [fixedWidth]="true") fa-icon([icon]="icon" [fixedWidth]="true")
span(*ngIf="showName") span(*ngIf="showName")
span.ml-1(*ngIf="name") span.ms-1(*ngIf="name")
| {{name}} | {{name}}
em.text-muted.ml-1 em.text-muted.ms-1
| {{name | translit}} | {{name | translit}}
span.text-muted.ml-1(*ngIf="!name") span.text-muted.ms-1(*ngIf="!name")
| <no name> | <no name>
span.badge.badge-success.ml-1(*ngIf="pledged") span.badge.badge-success.ms-1(*ngIf="pledged")
| ${{pledged}} | ${{pledged}}
@@ -1,5 +1,5 @@
span([class.extended]="extended") span([class.extended]="extended")
span.text-muted(*ngIf="loading") ... span.text-muted(*ngIf="loading") ...
auth-info-remote(*ngFor="let a of auths | slice:0:limit" [authId]="a" [showName]="extended") auth-info-remote(*ngFor="let a of auths | slice:0:limit" [authId]="a" [showName]="extended")
a.text-muted.ml-1.text-nowrap(*ngIf="auths.length > limit" (click)="limit = 9999") a.text-muted.ms-1.text-nowrap(*ngIf="auths.length > limit" (click)="limit = 9999")
small ({{auths.length - limit}} more) small ({{auths.length - limit}} more)
@@ -1,4 +1,4 @@
span([class.extended]="extended") span([class.extended]="extended")
auth-info(*ngFor="let a of fixedAuths | slice:0:limit" [auth]="a" [showName]="extended") auth-info(*ngFor="let a of fixedAuths | slice:0:limit" [auth]="a" [showName]="extended")
a.text-muted.ml-1.text-nowrap(*ngIf="fixedAuths.length > limit" (click)="limit = 9999") a.text-muted.ms-1.text-nowrap(*ngIf="fixedAuths.length > limit" (click)="limit = 9999")
small ({{fixedAuths.length - limit}} more) small ({{fixedAuths.length - limit}} more)
@@ -6,7 +6,7 @@ ng-template(#timeoutTooltip)
fa-icon([icon]="icon" [fixedWidth]="true" [ngClass]="className") fa-icon([icon]="icon" [fixedWidth]="true" [ngClass]="className")
fa-icon.text-alert.ban-icon-timer(*ngIf="isTimedOut" [icon]="clockIcon" [fixedWidth]="true") fa-icon.text-alert.ban-icon-timer(*ngIf="isTimedOut" [icon]="clockIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="clear()") a.dropdown-item((click)="clear()")
| clear #[b {{type}}] | clear #[b {{type}}]
a.dropdown-item((click)="perma()") a.dropdown-item((click)="perma()")
@@ -2,5 +2,5 @@ div(*ngIf="emails && emails.length")
.account-email.text-muted(*ngFor="let e of emails | slice:0:limit") .account-email.text-muted(*ngFor="let e of emails | slice:0:limit")
| {{e}} | {{e}}
div(*ngIf="hasMore") div(*ngIf="hasMore")
a.text-muted.ml-1.text-nowrap((click)="showMore()") a.text-muted.ms-1.text-nowrap((click)="showMore()")
small ({{emails.length - limit}} more) small ({{emails.length - limit}} more)
@@ -24,7 +24,7 @@ table.table.table-fixed.table-striped.table-hover.table-sm.table-ellipsis
fa-icon([icon]="clipboardIcon") fa-icon([icon]="clipboardIcon")
.text-muted.event-desc.pre-line(*ngIf="e.desc") .text-muted.event-desc.pre-line(*ngIf="e.desc")
span([innerHTML]="e.descHTML") span([innerHTML]="e.descHTML")
a.text-muted.ml-1([href]="translateUrl(e)" target="_blank" title="translate") a.text-muted.ms-1([href]="translateUrl(e)" target="_blank" title="translate")
fa-icon([icon]="langIcon") fa-icon([icon]="langIcon")
td.col-account td.col-account
account-info-remote(#accountInfo [accountId]="e.account" [showDuplicates]="true") account-info-remote(#accountInfo [accountId]="e.account" [showDuplicates]="true")
@@ -35,17 +35,17 @@ table.table.table-fixed.table-striped.table-hover.table-sm.table-ellipsis
td.col-origin td.col-origin
origin-info-remote([originIP]="e.origin?.ip") origin-info-remote([originIP]="e.origin?.ip")
td.col-actions.text-nowrap td.col-actions.text-nowrap
button.btn.btn-xs.btn-danger.mr-1((click)="remove(e)" title="Remove event") button.btn.btn-xs.btn-danger.me-1((click)="remove(e)" title="Remove event")
fa-icon([icon]="trashIcon") fa-icon([icon]="trashIcon")
.btn-group.dropdown(dropdown) .btn-group.dropdown(dropdown)
button.btn.btn-xs.btn-default( button.btn.btn-xs.btn-default(
(click)="onShowChat($event, e, accountInfo.account)" [disabled]="!e.account" title="Show chat log") (click)="onShowChat($event, e, accountInfo.account)" [disabled]="!e.account" title="Show chat log")
fa-icon([icon]="commentIcon") fa-icon([icon]="commentIcon")
button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-xs.btn-default.dropdown-toggle(dropdownToggle)
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="removeAll(e)") a.dropdown-item((click)="removeAll(e)")
fa-icon.mr-1([icon]="trashIcon" [fixedWidth]="true") fa-icon.me-1([icon]="trashIcon" [fixedWidth]="true")
| Remove all #[strong {{e.message}}] | Remove all #[strong {{e.message}}]
a.dropdown-item((click)="onAddChat(e, accountInfo.account)") a.dropdown-item((click)="onAddChat(e, accountInfo.account)")
fa-icon.mr-1([icon]="commentIcon" [fixedWidth]="true") fa-icon.me-1([icon]="commentIcon" [fixedWidth]="true")
| Add to chat log | Add to chat log
@@ -4,5 +4,5 @@
button.btn.btn-xs([ngClass]="on ? 'btn-success active' : 'btn-default'" (click)="onToggle(true)" [disabled]="disabled") button.btn.btn-xs([ngClass]="on ? 'btn-success active' : 'btn-default'" (click)="onToggle(true)" [disabled]="disabled")
b {{onText}} b {{onText}}
b.ml-2.mb-1.text-muted b.ms-2.mb-1.text-muted
| {{label}} | {{label}}
@@ -1,8 +1,8 @@
.d-flex.align-items-center(*ngIf="origin") .d-flex.align-items-center(*ngIf="origin")
a.origin-info-ip.mr-1([routerLink]="['/origins', origin.ip, origin.country]" [title]="origin.ip") a.origin-info-ip.me-1([routerLink]="['/origins', origin.ip, origin.country]" [title]="origin.ip")
| {{origin.ip}} | {{origin.ip}}
span([title]="countryName") [{{origin.country}}] span([title]="countryName") [{{origin.country}}]
span.badge.badge-none.ml-1(*ngIf="origin.accountsCount > 1" title="accounts using this IP") span.badge.badge-none.ms-1(*ngIf="origin.accountsCount > 1" title="accounts using this IP")
| {{origin.accountsCount}} | {{origin.accountsCount}}
ban-icon((toggle)="toggleBan('mute', $event)" [value]="origin.mute" type="mute") ban-icon((toggle)="toggleBan('mute', $event)" [value]="origin.mute" type="mute")
ban-icon((toggle)="toggleBan('shadow', $event)" [value]="origin.shadow" type="shadow") ban-icon((toggle)="toggleBan('shadow', $event)" [value]="origin.shadow" type="shadow")
@@ -4,7 +4,7 @@ ng-template(#tooltip)
.character-tooltip-indicator(*ngIf="isBadCM") • .character-tooltip-indicator(*ngIf="isBadCM") •
.character-tooltip-date .character-tooltip-date
from-now([time]="pony?.lastUsed") from-now([time]="pony?.lastUsed")
span.ml-1(*ngIf="pony?.deleted") [deleted] span.ms-1(*ngIf="pony?.deleted") [deleted]
span.cursor-pointer.badge( span.cursor-pointer.badge(
[ngClass]="labelClass" [class.deleted]="pony?.deleted" [class.badge-highlight]="highlight" (click)="click()" [ngClass]="labelClass" [class.deleted]="pony?.deleted" [class.badge-highlight]="highlight" (click)="click()"
@@ -1,17 +1,17 @@
div([class.pony-list-expanded]="expanded" [class.pony-list-deletable]="deletable") div([class.pony-list-expanded]="expanded" [class.pony-list-deletable]="deletable")
span.text-muted(*ngIf="loading") ... span.text-muted(*ngIf="loading") ...
span.pony-list-item.mr-1(*ngFor="let p of ponies | slice:0:limitTo") span.pony-list-item.me-1(*ngFor="let p of ponies | slice:0:limitTo")
pony-info-remote(#info [ponyId]="p" [highlight]="highlight(info.pony)") pony-info-remote(#info [ponyId]="p" [highlight]="highlight(info.pony)")
a.ml-1.icon-button.cursor-pointer((click)="remove(p)" title="delete character") a.ms-1.icon-button.cursor-pointer((click)="remove(p)" title="delete character")
fa-icon.text-muted([icon]="trashIcon" [fixedWidth]="true") fa-icon.text-muted([icon]="trashIcon" [fixedWidth]="true")
.btn-group.dropdown(dropdown *ngIf="duplicates") .btn-group.dropdown(dropdown *ngIf="duplicates")
a.ml-1.icon-button.cursor-pointer(dropdownToggle title="Assign to another account") a.ms-1.icon-button.cursor-pointer(dropdownToggle title="Assign to another account")
fa-icon.text-muted([icon]="assignIcon" [fixedWidth]="true") fa-icon.text-muted([icon]="assignIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
button.dropdown-item(*ngFor="let d of duplicates" (click)="assignTo(p, d.account)") button.dropdown-item(*ngFor="let d of duplicates" (click)="assignTo(p, d.account)")
span.text-muted assign to span.text-muted assign to
account-info-remote.ml-1([accountId]="d.account" [basic]="true") account-info-remote.ms-1([accountId]="d.account" [basic]="true")
a.text-muted.mr-1(*ngIf="!full && ponies.length > limit" (click)="toggleFull()") a.text-muted.me-1(*ngIf="!full && ponies.length > limit" (click)="toggleFull()")
small ({{ponies.length - limit}} more) small ({{ponies.length - limit}} more)
a.text-muted(*ngIf="full && ponies.length > limit" (click)="toggleFull()") a.text-muted(*ngIf="full && ponies.length > limit" (click)="toggleFull()")
small (less) small (less)
@@ -1,6 +1,6 @@
div(*ngIf="userAgent" [tooltip]="userAgent") div(*ngIf="userAgent" [tooltip]="userAgent")
fa-icon([icon]="browserClass" [fixedWidth]="true") fa-icon([icon]="browserClass" [fixedWidth]="true")
b.ml-1 {{browserVersion}} b.ms-1 {{browserVersion}}
fa-icon.ml-1([icon]="osClass" [fixedWidth]="true") fa-icon.ms-1([icon]="osClass" [fixedWidth]="true")
b.ml-1 {{osVersion}} b.ms-1 {{osVersion}}
fa-icon.ml-1([icon]="deviceClass" [fixedWidth]="true") fa-icon.ms-1([icon]="deviceClass" [fixedWidth]="true")
+1 -1
View File
@@ -29,7 +29,7 @@ h1(focusTitle) About
.row.team-members .row.team-members
.col-md-6(*ngFor="let c of credits") .col-md-6(*ngFor="let c of credits")
.team-member .team-member
.team-avatar.float-left( .team-avatar.float-start(
[style.background-image]="c.background" [style.background-image]="c.background"
[style.background-position]="c.position" [style.background-position]="c.position"
style="background-size: 328px 246px") style="background-size: 328px 246px")
+10 -10
View File
@@ -16,7 +16,7 @@ h1(focusTitle) Account settings
.form-group .form-group
label(for="birthdate") label(for="birthdate")
| Date of birth | Date of birth
fa-icon.ml-1.text-danger(*ngIf="showAccountAlert" [icon]="alertIcon" title="Missing field value") fa-icon.ms-1.text-danger(*ngIf="showAccountAlert" [icon]="alertIcon" title="Missing field value")
date-picker([(date)]="data.birthdate") date-picker([(date)]="data.birthdate")
.form-group(*ngIf="accountError") .form-group(*ngIf="accountError")
.alert.alert-danger .alert.alert-danger
@@ -24,7 +24,7 @@ h1(focusTitle) Account settings
.form-group(*ngIf="accountSaved") .form-group(*ngIf="accountSaved")
.alert.alert-success .alert.alert-success
| Changes saved | Changes saved
.form-group.text-right .form-group.text-end
button.btn.btn-default(type="submit" [disabled]="!canSubmit" style="min-width: 100px;") button.btn.btn-default(type="submit" [disabled]="!canSubmit" style="min-width: 100px;")
| {{saveButtonText}} | {{saveButtonText}}
@@ -40,8 +40,8 @@ h1(focusTitle) Account settings
ul.list-unstyled ul.list-unstyled
li.item-connected-account.d-flex.justify-content-between(*ngFor="let s of sites") li.item-connected-account.d-flex.justify-content-between(*ngFor="let s of sites")
a([href]="s.url" target="_blank" rel="noopener noreferrer") a([href]="s.url" target="_blank" rel="noopener noreferrer")
fa-icon.mr-1([icon]="icon(s.icon)" [fixedWidth]="true") fa-icon.me-1([icon]="icon(s.icon)" [fixedWidth]="true")
b #[span.sr-only {{s.icon}}] {{s.name}} b #[span.visually-hidden {{s.icon}}] {{s.name}}
button.btn.btn-sm.btn-danger(*ngIf="sites.length > 1" (click)="removeSite(s)" [disabled]="removingSite") button.btn.btn-sm.btn-danger(*ngIf="sites.length > 1" (click)="removeSite(s)" [disabled]="removingSite")
| remove | remove
@@ -57,8 +57,8 @@ h1(focusTitle) Account settings
| connect another social site to this account | connect another social site to this account
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item(*ngFor="let p of providers" (click)="connectSite(p)") button.dropdown-item(*ngFor="let p of providers" (click)="connectSite(p)")
fa-icon.mr-1([icon]="icon(p.id)" [fixedWidth]="true") fa-icon.me-1([icon]="icon(p.id)" [fixedWidth]="true")
| #[span.sr-only {{p.name}}] {{p.name}} | #[span.visually-hidden {{p.name}}] {{p.name}}
.form-group(*ngIf="mergeError") .form-group(*ngIf="mergeError")
.alert.alert-danger .alert.alert-danger
@@ -79,11 +79,11 @@ h1(focusTitle) Account settings
.col-md-6 .col-md-6
div(style="margin-bottom: 100px;") div(style="margin-bottom: 100px;")
.form-group .form-group
.float-right .float-end
span.text-muted Page: {{page + 1}} span.text-muted Page: {{page + 1}}
button.btn.btn-sm.btn-outline-secondary.ml-2((click)="page = page - 1; pageChanged()" [disabled]="!hides || page === 0") button.btn.btn-sm.btn-outline-secondary.ms-2((click)="page = page - 1; pageChanged()" [disabled]="!hides || page === 0")
| Previous page | Previous page
button.btn.btn-sm.btn-outline-secondary.ml-1((click)="page = page + 1; pageChanged()" [disabled]="!hides || hides.length < hidesPerPage") button.btn.btn-sm.btn-outline-secondary.ms-1((click)="page = page + 1; pageChanged()" [disabled]="!hides || hides.length < hidesPerPage")
| Next page | Next page
h3 Hidden players h3 Hidden players
@@ -94,6 +94,6 @@ h1(focusTitle) Account settings
.text-muted.text-center.p-4(*ngIf="!hides.length") no hidden players .text-muted.text-center.p-4(*ngIf="!hides.length") no hidden players
li.item-connected-account.d-flex.align-items-center(*ngFor="let h of hides") li.item-connected-account.d-flex.align-items-center(*ngFor="let h of hides")
b.flex-grow-1 {{h.name}} b.flex-grow-1 {{h.name}}
span.text-muted.mr-2 hidden {{h.date}} span.text-muted.me-2 hidden {{h.date}}
button.btn.btn-sm.btn-danger((click)="unhidePlayer(h)") button.btn.btn-sm.btn-danger((click)="unhidePlayer(h)")
| unhide player | unhide player
+5 -5
View File
@@ -34,15 +34,15 @@
.app-version .app-version
| version #[b {{version}}] | version #[b {{version}}]
.text-right .text-end
.d-flex.flex-wrap .d-flex.flex-wrap
//- .text-nowrap.mr-2 //- .text-nowrap.me-2
| &copy; 2019-{{date | date:'yyyy'}} | &copy; 2019-{{date | date:'yyyy'}}
| #[a.text-muted.mr-1([href]="twitterLink" target="_blank") {{copyright}}] | | #[a.text-muted.me-1([href]="twitterLink" target="_blank") {{copyright}}] |
.text-nowrap .text-nowrap
a.text-muted.mr-2(*ngIf="twitterLink" [href]="twitterLink" target="_blank" title="Twitter") a.text-muted.me-2(*ngIf="twitterLink" [href]="twitterLink" target="_blank" title="Twitter")
fa-icon([icon]="twitterIcon" [fixedWidth]="true") fa-icon([icon]="twitterIcon" [fixedWidth]="true")
a.text-muted.mr-2(*ngIf="contactEmail" href="mailto:{{contactEmail}}" target="_blank" title="Email") a.text-muted.me-2(*ngIf="contactEmail" href="mailto:{{contactEmail}}" target="_blank" title="Email")
fa-icon([icon]="emailIcon" [fixedWidth]="true") fa-icon([icon]="emailIcon" [fixedWidth]="true")
div div
a.text-muted.privacy-policy(href="/privacypolicy.html" target="_blank" rel="noopener") privacy policy a.text-muted.privacy-policy(href="/privacypolicy.html" target="_blank" rel="noopener") privacy policy
+3 -3
View File
@@ -17,7 +17,7 @@ main {
padding-bottom: 100px; padding-bottom: 100px;
flex-grow: 1; flex-grow: 1;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
padding-top: 20px; padding-top: 20px;
padding-bottom: 50px; padding-bottom: 50px;
} }
@@ -28,7 +28,7 @@ footer {
justify-content: space-between; justify-content: space-between;
padding-bottom: 20px; padding-bottom: 20px;
@include media-breakpoint-down(xs) { @include media-breakpoint-down(sm) {
white-space: normal !important; white-space: normal !important;
display: block; display: block;
font-size: 16px; font-size: 16px;
@@ -37,7 +37,7 @@ footer {
padding-bottom: 10px; padding-bottom: 10px;
} }
.text-right { .text-end {
text-align: left !important; text-align: left !important;
} }
+15 -15
View File
@@ -1,5 +1,5 @@
ng-template(#descriptionTooltip) ng-template(#descriptionTooltip)
.text-left .text-start
p Description and tags help you organize and search for your ponies. p Description and tags help you organize and search for your ponies.
p Use # tags to be able to quickly find specific ponies like #oc #winter or #unicorn p Use # tags to be able to quickly find specific ponies like #oc #winter or #unicorn
p p
@@ -10,8 +10,8 @@ page-loader(*ngIf="!playing")
.row(*ngIf="!playing && !loading") .row(*ngIf="!playing && !loading")
.col-lg-6.text-center .col-lg-6.text-center
h1.sr-only(focusTitle) Characters h1.visually-hidden(focusTitle) Characters
h2.sr-only Character selection h2.visually-hidden Character selection
.mx-auto(style="max-width: 400px;") .mx-auto(style="max-width: 400px;")
discord-button.mb-3 discord-button.mb-3
visit-pt-button.mb-3 visit-pt-button.mb-3
@@ -27,16 +27,16 @@ page-loader(*ngIf="!playing")
.form-group.text-center .form-group.text-center
button.btn.btn-lg.btn-default([disabled]="!canDuplicate" (click)="duplicate()" aria-label="Duplicate character") button.btn.btn-lg.btn-default([disabled]="!canDuplicate" (click)="duplicate()" aria-label="Duplicate character")
| Duplicate | Duplicate
button.btn.btn-lg.btn-default.ml-2([disabled]="!canRevert" (click)="revert()" aria-label="Revert changes") button.btn.btn-lg.btn-default.ms-2([disabled]="!canRevert" (click)="revert()" aria-label="Revert changes")
| Revert | Revert
button.btn.btn-lg.btn-default.ml-2([disabled]="!canSave" (click)="save()" aria-label="Save character") button.btn.btn-lg.btn-default.ms-2([disabled]="!canSave" (click)="save()" aria-label="Save character")
| Save | Save
play-box(label="Save & Play" [(error)]="error") play-box(label="Save & Play" [(error)]="error")
play-notice play-notice
.col-lg-6.character-tabs([setOutlineHidden]="!customOutlines" [class.character-tab-warning]="updateWarning") .col-lg-6.character-tabs([setOutlineHidden]="!customOutlines" [class.character-tab-warning]="updateWarning")
h2.sr-only Character customization h2.visually-hidden Character customization
tabset(type="pills" *ngIf="loaded" saveActiveTab="character-active-tab" label="Character customization") tabset(type="pills" *ngIf="loaded" saveActiveTab="character-active-tab" label="Character customization")
tab(title="body") tab(title="body")
.character-tab(*tabContent) .character-tab(*tabContent)
@@ -71,8 +71,8 @@ page-loader(*ngIf="!playing")
label.col-sm-4.col-form-label Export/Import options label.col-sm-4.col-form-label Export/Import options
.col-sm-8 .col-sm-8
button.btn.btn-sm.btn-default((click)="exportPony()") Export pony button.btn.btn-sm.btn-default((click)="exportPony()") Export pony
button.btn.btn-sm.btn-default.ml-1((click)="exportPonies()") Export all ponies button.btn.btn-sm.btn-default.ms-1((click)="exportPonies()") Export all ponies
button.btn.btn-sm.btn-default.ml-1((click)="importFile.click()") Import ponies button.btn.btn-sm.btn-default.ms-1((click)="importFile.click()") Import ponies
input.d-none(#importFile type="file" (change)="importPonies(importFile.files[0])") input.d-none(#importFile type="file" (change)="importPonies(importFile.files[0])")
.row.form-group .row.form-group
@@ -81,18 +81,18 @@ page-loader(*ngIf="!playing")
.dropdown.btn-group(dropdown) .dropdown.btn-group(dropdown)
button.btn.btn-default.dropdown-toggle( button.btn.btn-default.dropdown-toggle(
dropdownToggle aria-labelledby="social-site-label" aria-describedby="social-site-help") dropdownToggle aria-labelledby="social-site-label" aria-describedby="social-site-help")
fa-icon.mr-1( fa-icon.me-1(
*ngIf="site?.icon" [icon]="icon(site.icon)" [fixedWidth]="true" [style.color]="site.color" *ngIf="site?.icon" [icon]="icon(site.icon)" [fixedWidth]="true" [style.color]="site.color"
size="lg" [attr.aria-label]="site.icon") size="lg" [attr.aria-label]="site.icon")
strong {{site?.name}} strong {{site?.name}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let s of sites" (click)="site = s") a.dropdown-item(*ngFor="let s of sites" (click)="site = s")
fa-icon.mr-1( fa-icon.me-1(
*ngIf="s.icon" [icon]="icon(s.icon)" [fixedWidth]="true" [style.color]="s.color" *ngIf="s.icon" [icon]="icon(s.icon)" [fixedWidth]="true" [style.color]="s.color"
size="lg" [attr.aria-label]="s.icon") size="lg" [attr.aria-label]="s.icon")
strong {{s.name}} strong {{s.name}}
.dropdown.btn-group.ml-1(dropdown *ngIf="tags.length > 1") .dropdown.btn-group.ms-1(dropdown *ngIf="tags.length > 1")
button.btn.btn-default.dropdown-toggle(dropdownToggle aria-label="Show tag") button.btn.btn-default.dropdown-toggle(dropdownToggle aria-label="Show tag")
span.badge(*ngIf="tag.id" [ngClass]="'badge-' + tag.className") {{tag.id}} span.badge(*ngIf="tag.id" [ngClass]="'badge-' + tag.className") {{tag.id}}
strong(*ngIf="!tag.id") {{tag.name}} strong(*ngIf="!tag.id") {{tag.name}}
@@ -107,7 +107,7 @@ page-loader(*ngIf="!playing")
.row.form-group .row.form-group
label.col-sm-4.col-form-label(for="description") label.col-sm-4.col-form-label(for="description")
| Description | Description
fa-icon.text-muted.ml-2([icon]="infoIcon" [tooltip]="descriptionTooltip" containerClass="tooltip-desc") fa-icon.text-muted.ms-2([icon]="infoIcon" [tooltip]="descriptionTooltip" containerClass="tooltip-desc")
.col-sm-8 .col-sm-8
input.form-control#description( input.form-control#description(
[(ngModel)]="pony.desc" placeholder="example: with a hat #oc #winter" [maxlength]="maxDescLength") [(ngModel)]="pony.desc" placeholder="example: with a hat #oc #winter" [maxlength]="maxDescLength")
@@ -125,7 +125,7 @@ page-loader(*ngIf="!playing")
.input-group-append.dropdown(*ngIf="canSaveFiles" dropdown) .input-group-append.dropdown(*ngIf="canSaveFiles" dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle *ngIf="canExport" aria-label="Export / Import") button.btn.btn-default.dropdown-toggle(dropdownToggle *ngIf="canExport" aria-label="Export / Import")
fa-icon([icon]="codeIcon") fa-icon([icon]="codeIcon")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="export()") export all a.dropdown-item((click)="export()") export all
a.dropdown-item((click)="import()") import data a.dropdown-item((click)="import()") import data
a.dropdown-item((click)="testSize()") print compressed a.dropdown-item((click)="testSize()") print compressed
@@ -137,7 +137,7 @@ page-loader(*ngIf="!playing")
fa-icon([icon]="saveIcon") fa-icon([icon]="saveIcon")
button.btn.btn-default.dropdown-toggle(dropdownToggle style="min-width: 80px") button.btn.btn-default.dropdown-toggle(dropdownToggle style="min-width: 80px")
strong {{animations[activeAnimation]().name}} strong {{animations[activeAnimation]().name}}
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item(*ngFor="let a of animations; let i = index" (click)="setActiveAnimation(i)") a.dropdown-item(*ngFor="let a of animations; let i = index" (click)="setActiveAnimation(i)")
| {{a().name}} | {{a().name}}
@@ -382,7 +382,7 @@ page-loader(*ngIf="!playing")
.accessory-tab(*tabContent) .accessory-tab(*tabContent)
.form-group.d-flex.justify-content-center.pt-2 .form-group.d-flex.justify-content-center.pt-2
custom-checkbox([(checked)]="previewExtra") show preview custom-checkbox([(checked)]="previewExtra") show preview
em.text-muted.ml-2 em.text-muted.ms-2
| (you have to enable these accessories in-game) | (you have to enable these accessories in-game)
set-selection( set-selection(
label="Extra accessories" [set]="info.extraAccessory" [sets]="extraAccessories" label="Extra accessories" [set]="info.extraAccessory" [sets]="extraAccessories"
@@ -28,7 +28,7 @@
background: $grass-color; background: $grass-color;
border-radius: $border-radius-lg; border-radius: $border-radius-lg;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
width: 280px; width: 280px;
height: 280px; height: 280px;
} }
@@ -49,7 +49,7 @@
justify-content: space-between; justify-content: space-between;
> .lock-box { > .lock-box {
@include media-breakpoint-down(xs) { @include media-breakpoint-down(sm) {
margin-right: 0; margin-right: 0;
margin-bottom: 5px; margin-bottom: 5px;
} }
+13 -13
View File
@@ -2,17 +2,17 @@
button.game-button.px-2((click)="toggleEditor()") button.game-button.px-2((click)="toggleEditor()")
fa-icon([icon]="editIcon") fa-icon([icon]="editIcon")
.d-flex.align-items-start.pl-2.pt-1(*ngIf="hasEditor") .d-flex.align-items-start.ps-2.pt-1(*ngIf="hasEditor")
.dropdown-menu.p-0(*ngIf="hasSelectedEntities" style="display: block; width: 500px; position: absolute; top: 36px; left: 0;") .dropdown-menu.p-0(*ngIf="hasSelectedEntities" style="display: block; width: 500px; position: absolute; top: 36px; left: 0;")
.px-2 .px-2
//- name //- name
div div
.row.form-group.mb-2 .row.form-group.mb-2
label.col-12.col-form-label label.col-12.col-form-label
.float-right .float-end
button.btn.btn-xs.btn-dark.ml-1((click)="showEntitiesInfo()" title="Show info") button.btn.btn-xs.btn-dark.ms-1((click)="showEntitiesInfo()" title="Show info")
| info | info
button.btn.btn-xs.btn-danger.ml-1((click)="deleteEntities()" title="Delete entities") button.btn.btn-xs.btn-danger.ms-1((click)="deleteEntities()" title="Delete entities")
fa-icon([icon]="deleteIcon") fa-icon([icon]="deleteIcon")
| {{entityName}} | {{entityName}}
@@ -70,7 +70,7 @@
a.dropdown-item(*ngFor="let e of editorEntities" (click)="editorEntity = e") a.dropdown-item(*ngFor="let e of editorEntities" (click)="editorEntity = e")
| {{e}} | {{e}}
.dropdown.ml-1(dropdown) .dropdown.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle)
fa-icon([icon]="cogIcon") fa-icon([icon]="cogIcon")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -83,21 +83,21 @@
div(*ngIf="dev") div(*ngIf="dev")
h6.dropdown-header Show (numpad 4) h6.dropdown-header Show (numpad 4)
a.dropdown-item(*ngFor="let field of showFields" (click)="toggleShow(field); $event.stopPropagation()") a.dropdown-item(*ngFor="let field of showFields" (click)="toggleShow(field); $event.stopPropagation()")
fa-icon.mr-1([icon]="isShow(field) ? checkIcon : emptyIcon" [fixedWidth]="true") fa-icon.me-1([icon]="isShow(field) ? checkIcon : emptyIcon" [fixedWidth]="true")
| {{field}} | {{field}}
button.btn.btn-sm.btn-default.ml-1( button.btn.btn-sm.btn-default.ms-1(
[btnHighlight]="selectingEntities" (click)="toggleSelecting()" title="Select entities") [btnHighlight]="selectingEntities" (click)="toggleSelecting()" title="Select entities")
fa-icon([icon]="selectIcon") fa-icon([icon]="selectIcon")
.dropdown.ml-1(dropdown) .dropdown.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle)
| tile: {{tiles[editorTile + 1]}} | tile: {{tiles[editorTile + 1]}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let t of tiles; let i = index" (click)="editorTile = i - 1") a.dropdown-item(*ngFor="let t of tiles; let i = index" (click)="editorTile = i - 1")
| {{t}} | {{t}}
.dropdown.ml-1(dropdown) .dropdown.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle)
| brush: {{editor.brushSize}} | brush: {{editor.brushSize}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -108,7 +108,7 @@
a.dropdown-item((click)="editor.brushSize = 5") 5 a.dropdown-item((click)="editor.brushSize = 5") 5
a.dropdown-item((click)="editor.brushSize = 6") 6 a.dropdown-item((click)="editor.brushSize = 6") 6
.dropdown.ml-1(dropdown [autoClose]="false") .dropdown.ms-1(dropdown [autoClose]="false")
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle)
| global | global
.dropdown-menu(*dropdownMenu style="width: 400px") .dropdown-menu(*dropdownMenu style="width: 400px")
@@ -125,14 +125,14 @@
.col-7.py-2 .col-7.py-2
slider-bar([(value)]="shadowOpacity" [min]="0" [max]="255") slider-bar([(value)]="shadowOpacity" [min]="0" [max]="255")
.dropdown.ml-1(dropdown) .dropdown.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle)
| engine | engine
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let e of engines" (click)="setEngine(e)" [class.active]="isActiveEngine(e)") a.dropdown-item(*ngFor="let e of engines" (click)="setEngine(e)" [class.active]="isActiveEngine(e)")
| {{e.name}} | {{e.name}}
.btn.btn-sm.btn-default.disabled.ml-1(*ngIf="hasElevation") .btn.btn-sm.btn-default.disabled.ms-1(*ngIf="hasElevation")
| elevation: {{editorElevation}} | elevation: {{editorElevation}}
.btn.btn-sm.btn-default.disabled.ml-1(*ngIf="hasElevation") .btn.btn-sm.btn-default.disabled.ms-1(*ngIf="hasElevation")
| special: {{editorSpecial}} | special: {{editorSpecial}}
+3 -3
View File
@@ -18,7 +18,7 @@ h1(focusTitle) Help
ul.spaced-list ul.spaced-list
li li
b movement b movement
.pl-2.mb-1. .ps-2.mb-1.
Use Use
#[kbd-key(title="up arrow key"): fa-icon([icon]="upIcon")] #[kbd-key(title="up arrow key"): fa-icon([icon]="upIcon")]
#[kbd-key(title="left arrow key"): fa-icon([icon]="leftIcon")] #[kbd-key(title="left arrow key"): fa-icon([icon]="leftIcon")]
@@ -36,7 +36,7 @@ h1(focusTitle) Help
Hold #[kbd-key(title="shift key") shift] to walk slowly. Hold #[kbd-key(title="shift key") shift] to walk slowly.
li li
b chat b chat
.pl-2.mb-1. .ps-2.mb-1.
Use #[kbd-key(title="enter key") enter] Use #[kbd-key(title="enter key") enter]
or #[kbd-key.gamepad.gamepad-blue(title="Gamepad X button") X] or #[kbd-key.gamepad.gamepad-blue(title="Gamepad X button") X]
to open chat box and send a message. to open chat box and send a message.
@@ -167,7 +167,7 @@ h1(focusTitle) Help
.emotes .emotes
ul ul
li(*ngFor="let e of emotes") li(*ngFor="let e of emotes")
span.emote-sample.mr-2 span.emote-sample.me-2
emote-box([emote]="e") emote-box([emote]="e")
| :{{e}}: | :{{e}}:
+1 -1
View File
@@ -6,7 +6,7 @@ div(*ngIf="!playing")
page-loader page-loader
div(*ngIf="!loading") div(*ngIf="!loading")
h1.sr-only(focusTitle) Home h1.visually-hidden(focusTitle) Home
.form-group(*ngIf="authError") .form-group(*ngIf="authError")
.alert.alert-danger(role="alert") .alert.alert-danger(role="alert")
+3 -3
View File
@@ -3,7 +3,7 @@
.home-logo { .home-logo {
width: 574px; width: 574px;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
width: 287px; width: 287px;
} }
} }
@@ -12,7 +12,7 @@
max-width: 400px; max-width: 400px;
margin-top: 50px; margin-top: 50px;
@include media-breakpoint-down(md) { @include media-breakpoint-down(lg) {
margin-top: 15px; margin-top: 15px;
} }
} }
@@ -20,7 +20,7 @@
.heading { .heading {
margin-bottom: 50px; margin-bottom: 50px;
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
margin-bottom: 20px; margin-bottom: 20px;
} }
} }
@@ -9,13 +9,13 @@
tab(title="Actions" [icon]="actionsIcon") tab(title="Actions" [icon]="actionsIcon")
.action-columns(*tabContent) .action-columns(*tabContent)
.d-flex.align-items-center.mb-2(*ngFor="let a of actions") .d-flex.align-items-center.mb-2(*ngFor="let a of actions")
action-button.mb-0.mr-2([draggableItem]="a" [action]="a" [shadow]="false") action-button.mb-0.me-2([draggableItem]="a" [action]="a" [shadow]="false")
b {{a.title}} b {{a.title}}
tab(title="Expressions" [icon]="expressionsIcon") tab(title="Expressions" [icon]="expressionsIcon")
div(*tabContent) div(*tabContent)
.d-flex.mb-3 .d-flex.mb-3
action-button.mb-0.mr-sm-4( action-button.mb-0.me-sm-4(
[draggableItem]="emoteAction" [action]="emoteAction" [shadow]="false" (draggableDrop)="drop($event)") [draggableItem]="emoteAction" [action]="emoteAction" [shadow]="false" (draggableDrop)="drop($event)")
.sub-tabset.nav.nav-pills.mb-0 .sub-tabset.nav.nav-pills.mb-0
button.btn-unstyled.nav-link([class.active]="activeTab === 'right-eye'" (click)="activeTab = 'right-eye'") Right eye button.btn-unstyled.nav-link([class.active]="activeTab === 'right-eye'" (click)="activeTab = 'right-eye'") Right eye
@@ -58,37 +58,37 @@
[invisible]="tabIndex !== 1 || activeTab !== 'extra'" [invisible]="tabIndex !== 1 || activeTab !== 'extra'"
[circle]="coatFill" [reverseExtra]="true" (selectedChange)="changed(lockEyes)") [circle]="coatFill" [reverseExtra]="true" (selectedChange)="changed(lockEyes)")
.d-flex.flex-wrap.mt-3 .d-flex.flex-wrap.mt-3
label.text-muted.mr-3 Other options label.text-muted.me-3 Other options
custom-checkbox([(checked)]="blush" (checkedChange)="changed(lockEyes)") Blush custom-checkbox([(checked)]="blush" (checkedChange)="changed(lockEyes)") Blush
custom-checkbox.ml-4([(checked)]="sleeping" (checkedChange)="changed(lockEyes)") Sleeping custom-checkbox.ms-4([(checked)]="sleeping" (checkedChange)="changed(lockEyes)") Sleeping
custom-checkbox.ml-4([(checked)]="tears" (checkedChange)="changed(lockEyes)") Tears custom-checkbox.ms-4([(checked)]="tears" (checkedChange)="changed(lockEyes)") Tears
custom-checkbox.ml-4([(checked)]="crying" (checkedChange)="changed(lockEyes)") Crying custom-checkbox.ms-4([(checked)]="crying" (checkedChange)="changed(lockEyes)") Crying
custom-checkbox.ml-4([(checked)]="hearts" (checkedChange)="changed(lockEyes)") Hearts custom-checkbox.ms-4([(checked)]="hearts" (checkedChange)="changed(lockEyes)") Hearts
tab(title="Chat" [icon]="chatIcon") tab(title="Chat" [icon]="chatIcon")
.action-columns(*tabContent) .action-columns(*tabContent)
.d-flex.align-items-center.mb-2(*ngFor="let a of commands") .d-flex.align-items-center.mb-2(*ngFor="let a of commands")
action-button.mb-0.mr-2([draggableItem]="a" [action]="a" [shadow]="false") action-button.mb-0.me-2([draggableItem]="a" [action]="a" [shadow]="false")
b {{a.title}} b {{a.title}}
tab(title="Options" [icon]="optionsIcon") tab(title="Options" [icon]="optionsIcon")
div(*tabContent) div(*tabContent)
button.btn.btn-outline-secondary.mr-2.mb-2((click)="resetToDefault()") button.btn.btn-outline-secondary.me-2.mb-2((click)="resetToDefault()")
| Reset to default actions | Reset to default actions
button.btn.btn-outline-secondary.mr-2.mb-2((click)="clearActionBar()") button.btn.btn-outline-secondary.me-2.mb-2((click)="clearActionBar()")
| Clear action bar | Clear action bar
button.btn.btn-outline-secondary.mr-2.mb-2((click)="undo()") button.btn.btn-outline-secondary.me-2.mb-2((click)="undo()")
| Undo | Undo
button.btn.btn-outline-secondary.mr-2.mb-2((click)="export()") button.btn.btn-outline-secondary.me-2.mb-2((click)="export()")
| Export actions | Export actions
button.btn.btn-outline-secondary.mr-2.mb-2((click)="importFile.click()") button.btn.btn-outline-secondary.me-2.mb-2((click)="importFile.click()")
| Import actions | Import actions
input.d-none(#importFile type="file" (change)="import(importFile.files[0])") input.d-none(#importFile type="file" (change)="import(importFile.files[0])")
tab(*ngIf="dev" title="Dev" [icon]="devIcon") tab(*ngIf="dev" title="Dev" [icon]="devIcon")
div(*tabContent) div(*tabContent)
.d-flex.mb-3 .d-flex.mb-3
action-button.mb-0.mr-4( action-button.mb-0.me-4(
[draggableItem]="entityAction" [action]="entityAction" [shadow]="false" (draggableDrop)="drop($event)") [draggableItem]="entityAction" [action]="entityAction" [shadow]="false" (draggableDrop)="drop($event)")
input.form-control( input.form-control(
placeholder="entity name" [(ngModel)]="entityName" (ngModelChange)="updateEntity()" style="max-width: 200px;") placeholder="entity name" [(ngModel)]="entityName" (ngModelChange)="updateEntity()" style="max-width: 200px;")
@@ -4,7 +4,7 @@
.col-sm-7.mb-1 .col-sm-7.mb-1
button.btn.btn-primary((click)="clearCM()" title="Clear all") button.btn.btn-primary((click)="clearCM()" title="Clear all")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.btn-group.ml-1(btnRadioGroup [(ngModel)]="state.brushType") .btn-group.ms-1(btnRadioGroup [(ngModel)]="state.brushType")
button.btn.btn-primary(btnRadio="eraser" title="Eraser") button.btn.btn-primary(btnRadio="eraser" title="Eraser")
fa-icon([icon]="eraserIcon" [fixedWidth]="true") fa-icon([icon]="eraserIcon" [fixedWidth]="true")
button.btn.btn-primary(btnRadio="eyedropper" title="Eyedropper") button.btn.btn-primary(btnRadio="eyedropper" title="Eyedropper")
@@ -1,4 +1,4 @@
.sr-only(#ariaAnnounce aria-live="assertive") .visually-hidden(#ariaAnnounce aria-live="assertive")
.character-list([class.character-list-searchable]="searchable" [class.in-game]="inGame") .character-list([class.character-list-searchable]="searchable" [class.in-game]="inGame")
@@ -9,9 +9,9 @@
#searchInput type="search" [placeholder]="placeholder" [(ngModel)]="search" (input)="updatePonies()" #searchInput type="search" [placeholder]="placeholder" [(ngModel)]="search" (input)="updatePonies()"
autocomplete="nope") autocomplete="nope")
.input-group-append(*ngIf="tags.length" #tagsDropdown="ag-dropdown" dropdown) .input-group-append(*ngIf="tags.length" #tagsDropdown="ag-dropdown" dropdown)
button.btn.btn-secondary.rounded-right(dropdownToggle title="Search by tags") button.btn.btn-secondary.rounded-end(dropdownToggle title="Search by tags")
fa-icon([icon]="hashIcon") fa-icon([icon]="hashIcon")
.dropdown-menu.dropdown-menu-right.shadow.tag-list(*dropdownMenu) .dropdown-menu.dropdown-menu-end.shadow.tag-list(*dropdownMenu)
button.dropdown-item(*ngFor="let tag of tags" (click)="search = tag; tagsDropdown.close(); updatePonies()") button.dropdown-item(*ngFor="let tag of tags" (click)="search = tag; tagsDropdown.close(); updatePonies()")
| {{tag}} | {{tag}}
@@ -1,4 +1,4 @@
.sr-only(#ariaAnnounce aria-live="assertive") .visually-hidden(#ariaAnnounce aria-live="assertive")
.character-select.input-group .character-select.input-group
input.form-control.text-center( input.form-control.text-center(
@@ -7,7 +7,7 @@
} }
character-list { character-list {
@include media-breakpoint-down(sm) { @include media-breakpoint-down(md) {
left: auto; left: auto;
right: 0; right: 0;
} }
@@ -9,7 +9,7 @@
ul ul
li(*ngFor="let e of emotes" (click)="addEmoji(e.symbol)" li(*ngFor="let e of emotes" (click)="addEmoji(e.symbol)"
) )
span.emote-sample.mr-2 span.emote-sample.me-2
emote-box([emote]="e.names[0]") emote-box([emote]="e.names[0]")
emote-box.game-button.chat-emoji-button([emote]="btnEmoji" (click)="toggleEmojiBox()" (mouseenter)="onMouseEnterEmojiButton($event)") emote-box.game-button.chat-emoji-button([emote]="btnEmoji" (click)="toggleEmojiBox()" (mouseenter)="onMouseEnterEmojiButton($event)")
@@ -109,7 +109,7 @@ export function createChatLogLineDOM(clickLabel: ClickHandler, clickName: ClickH
line.index = element('span', 'chat-line-time-index', [line.indexText = textNode('')]), line.index = element('span', 'chat-line-time-index', [line.indexText = textNode('')]),
]), ]),
line.label = element( line.label = element(
'span', 'chat-line-label mr-1', [line.labelText = textNode('')], undefined, { click: () => clickLabel(line.entry) }), 'span', 'chat-line-label me-1', [line.labelText = textNode('')], undefined, { click: () => clickLabel(line.entry) }),
line.prefixText = textNode(''), line.prefixText = textNode(''),
line.name = element('span', 'chat-line-name', [ line.name = element('span', 'chat-line-name', [
textNode('['), textNode('['),
@@ -16,7 +16,7 @@
//-[style.border-left-color]="indicatorColor" //-[style.border-left-color]="indicatorColor"
a.color-picker-chevron((mousedown)="toggleOpen()" [hidden]="isDisabled" aria-label="Pick color") a.color-picker-chevron((mousedown)="toggleOpen()" [hidden]="isDisabled" aria-label="Pick color")
fa-icon([icon]="chevronIcon" [fixedWidth]="true") fa-icon([icon]="chevronIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right.color-picker-menu.show( .dropdown-menu.dropdown-menu-end.color-picker-menu.show(
(mousedown)="stopEvent($event)" *ngIf="isOpen" aria-hidden="true") (mousedown)="stopEvent($event)" *ngIf="isOpen" aria-hidden="true")
.color-picker-sv( .color-picker-sv(
[style.background-color]="hue" (agDrag)="dragSV($event)" agDragRelative="self" [agDragPrevent]="true") [style.background-color]="hue" (agDrag)="dragSV($event)" agDragRelative="self" [agDragPrevent]="true")
@@ -1,11 +1,11 @@
.custom-control.custom-checkbox.mb-2([class.disabled]="disabled") .form-check.custom-checkbox.mb-2([class.disabled]="disabled")
label input.form-check-input(
input.custom-control-input( type="checkbox"
type="checkbox" [id]="id"
[disabled]="disabled" [disabled]="disabled"
[(ngModel)]="checked" [(ngModel)]="checked"
(ngModelChange)="checkedChange.emit(checked)" (ngModelChange)="checkedChange.emit(checked)"
[attr.aria-describedby]="help ? helpId : undefined") [attr.aria-describedby]="help ? helpId : undefined")
.custom-control-label label.form-check-label([for]="id")
ng-content ng-content
small.form-text.text-muted.mt-0(*ngIf="help" [id]="helpId") {{help}} small.form-text.text-muted.mt-0(*ngIf="help" [id]="helpId") {{help}}
@@ -13,5 +13,6 @@ export class CustomCheckbox {
@Input() help = ''; @Input() help = '';
@Input() checked = false; @Input() checked = false;
@Output() checkedChange = new EventEmitter<boolean>(); @Output() checkedChange = new EventEmitter<boolean>();
id = uniqueId('custom-checkbox-');
helpId = uniqueId('custom-checkbox-help-'); helpId = uniqueId('custom-checkbox-help-');
} }
@@ -1,10 +1,10 @@
.d-flex .d-flex
select.form-control.w-50(placeholder="Day" [(ngModel)]="day" (ngModelChange)="change()") select.form-select.w-50(placeholder="Day" [(ngModel)]="day" (ngModelChange)="change()")
option(disabled [ngValue]="0") Day option(disabled [ngValue]="0") Day
option(*ngFor="let d of days" [ngValue]="d") {{d}} option(*ngFor="let d of days" [ngValue]="d") {{d}}
select.form-control.ml-2(placeholder="Month" [(ngModel)]="month" (ngModelChange)="change()") select.form-select.ms-2(placeholder="Month" [(ngModel)]="month" (ngModelChange)="change()")
option(disabled [ngValue]="0") Month option(disabled [ngValue]="0") Month
option(*ngFor="let m of months; let i = index" [ngValue]="i + 1") {{m}} option(*ngFor="let m of months; let i = index" [ngValue]="i + 1") {{m}}
select.form-control.ml-2.w-50(placeholder="Year" [(ngModel)]="year" (ngModelChange)="change()") select.form-select.ms-2.w-50(placeholder="Year" [(ngModel)]="year" (ngModelChange)="change()")
option(disabled [ngValue]="0") Year option(disabled [ngValue]="0") Year
option(*ngFor="let y of years" [ngValue]="y") {{y}} option(*ngFor="let y of years" [ngValue]="y") {{y}}
@@ -1,4 +1,4 @@
a.btn.btn-lg.btn-outline-discord.btn-block.mb-2( a.btn.btn-lg.btn-outline-discord.d-block.w-100.mb-2(
*ngIf="discordLink" (mouseenter)="pony.excite()" (mouseout)="pony.reset()" [href]="discordLink" target="_blank" *ngIf="discordLink" (mouseenter)="pony.excite()" (mouseout)="pony.reset()" [href]="discordLink" target="_blank"
rel="noopener noreferrer") rel="noopener noreferrer")
| Join us on Discord! | Join us on Discord!
@@ -12,7 +12,7 @@
} }
.col-outline { .col-outline {
@include media-breakpoint-down(xs) { @include media-breakpoint-down(sm) {
padding-top: 0.5rem; padding-top: 0.5rem;
} }
} }
@@ -3,7 +3,7 @@
[preventAutoCloseOnOutlet]="true") [preventAutoCloseOnOutlet]="true")
button.game-button.dropdown-toggle.no-arrow(dropdownToggle (click)="false" title="Friends") button.game-button.dropdown-toggle.no-arrow(dropdownToggle (click)="false" title="Friends")
fa-icon([icon]="friendsIcon" [fixedWidth]="true") fa-icon([icon]="friendsIcon" [fixedWidth]="true")
.friends-dropdown-menu.dropdown-menu.dropdown-menu-right(*dropdownMenu) .friends-dropdown-menu.dropdown-menu.dropdown-menu-end(*dropdownMenu)
.friends-list-header.list-unstyled .friends-list-header.list-unstyled
.dropdown-header.d-flex .dropdown-header.d-flex
.flex-grow-1 Friends .flex-grow-1 Friends
@@ -11,13 +11,13 @@
button.dropdown-toggle.no-arrow(dropdownToggle) button.dropdown-toggle.no-arrow(dropdownToggle)
span.text-success(*ngIf="!hidden") online span.text-success(*ngIf="!hidden") online
span.text-muted(*ngIf="hidden") offline span.text-muted(*ngIf="hidden") offline
fa-icon.ml-2([icon]="cogIcon") fa-icon.ms-2([icon]="cogIcon")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
button.dropdown-item((click)="setStatus('online')") button.dropdown-item((click)="setStatus('online')")
fa-icon.mr-2.text-success([icon]="statusIcon" size="xs" [fixedWidth]="true") fa-icon.me-2.text-success([icon]="statusIcon" size="xs" [fixedWidth]="true")
| Online | Online
button.dropdown-item((click)="setStatus('invisible')") button.dropdown-item((click)="setStatus('invisible')")
fa-icon.mr-2.text-muted([icon]="statusIcon" size="xs" [fixedWidth]="true") fa-icon.me-2.text-muted([icon]="statusIcon" size="xs" [fixedWidth]="true")
| Show as Offline | Show as Offline
.friends-list(*ngIf="friends && friends.length; else noFriends") .friends-list(*ngIf="friends && friends.length; else noFriends")
//- [itemSize]="42") //- [itemSize]="42")
@@ -30,17 +30,17 @@
[focusOnOpen]="false" [focusOnOpen]="false"
[focusOnClose]="false") [focusOnClose]="false")
button.d-flex(dropdownToggle) button.d-flex(dropdownToggle)
portrait-box.mr-2([pony]="f.ponyInfo" size="small" [noBorder]="true") portrait-box.me-2([pony]="f.ponyInfo" size="small" [noBorder]="true")
.flex-grow-1.friends-item-details .flex-grow-1.friends-item-details
.friends-item-name {{f.actualName}}&#160; .friends-item-name {{f.actualName}}&#160;
.friends-item-more .friends-item-more
.text-success.float-right.ml-2(*ngIf="f.online") online .text-success.float-end.ms-2(*ngIf="f.online") online
.text-muted.float-right.ml-2(*ngIf="!f.online") offline .text-muted.float-end.ms-2(*ngIf="!f.online") offline
.text-muted.friends-item-account {{f.accountName}} .text-muted.friends-item-account {{f.accountName}}
.friends-item-delete.d-flex.px-2.py-1(*ngIf="removing === f") .friends-item-delete.d-flex.px-2.py-1(*ngIf="removing === f")
button.btn.btn-sm.btn-outline-success.flex-grow-1((click)="cancelRemove(); $event.stopPropagation()") button.btn.btn-sm.btn-outline-success.flex-grow-1((click)="cancelRemove(); $event.stopPropagation()")
| Cancel | Cancel
button.btn.btn-sm.btn-outline-danger.flex-grow-1.ml-2((click)="confirmRemove(); $event.stopPropagation()") button.btn.btn-sm.btn-outline-danger.flex-grow-1.ms-2((click)="confirmRemove(); $event.stopPropagation()")
| Confirm remove | Confirm remove
//- span.badge.badge-none.friends-item-server PG //- span.badge.badge-none.friends-item-server PG
.options-dropdown-menu.dropdown-menu(*dropdownMenu) .options-dropdown-menu.dropdown-menu(*dropdownMenu)
@@ -11,7 +11,7 @@
.d-flex.align-items-center .d-flex.align-items-center
portrait-box([pony]="i.pony" size="small" [noBorder]="true" style="margin: -5px 10px -5px -10px;") portrait-box([pony]="i.pony" size="small" [noBorder]="true" style="margin: -5px 10px -5px -10px;")
b {{i.name}} b {{i.name}}
span.text-muted.ml-1(*ngIf="!i.active") (inactive) span.text-muted.ms-1(*ngIf="!i.active") (inactive)
button.btn.btn-xs.btn-outline-danger Cancel button.btn.btn-xs.btn-outline-danger Cancel
.alert.alert-danger.mt-3.mb-0(*ngIf="error") .alert.alert-danger.mt-3.mb-0(*ngIf="error")
+14 -14
View File
@@ -4,12 +4,12 @@ nav.navbar.navbar-expand.justify-content-end(role="navigation")
img.pixelart.logo-large(revSrc="images/logo-large.png" alt="pixel.horse" width="287" height="65") img.pixelart.logo-large(revSrc="images/logo-large.png" alt="pixel.horse" width="287" height="65")
img.pixelart.logo-small(revSrc="images/logo-small.png" alt="pixel.horse" width="37" height="43") img.pixelart.logo-small(revSrc="images/logo-small.png" alt="pixel.horse" width="37" height="43")
.navbar-collapse.text-right .navbar-collapse.text-end
.navbar-nav.ml-auto .navbar-nav.ms-auto
ng-content ng-content
.dropdown(*ngIf="account" #dropdown="ag-dropdown" dropdown autoClose="outsideClick") .dropdown(*ngIf="account" #dropdown="ag-dropdown" dropdown autoClose="outsideClick")
button.btn.cursor-pointer.dropdown-toggle(dropdownToggle [attr.aria-label]="'Signed-in as ' + account.name") button.btn.cursor-pointer.dropdown-toggle(dropdownToggle [attr.aria-label]="'Signed-in as ' + account.name")
fa-icon.mr-1( fa-icon.me-1(
*ngIf="hasSupporterIcon" [icon]="starIcon" [ngClass]="supporterClass" *ngIf="hasSupporterIcon" [icon]="starIcon" [ngClass]="supporterClass"
[title]="supporterTitle" [attr.aria-label]="supporterTitle" aria-hidden="true") [title]="supporterTitle" [attr.aria-label]="supporterTitle" aria-hidden="true")
.d-none.d-sm-inline(aria-hidden="true") {{account.name}} .d-none.d-sm-inline(aria-hidden="true") {{account.name}}
@@ -18,24 +18,24 @@ nav.navbar.navbar-expand.justify-content-end(role="navigation")
fa-icon.text-danger.account-alert-icon( fa-icon.text-danger.account-alert-icon(
*ngIf="showAccountAlert" [icon]="alertIcon" [fixedWidth]="true" size="sm" aria-hidden="true") *ngIf="showAccountAlert" [icon]="alertIcon" [fixedWidth]="true" size="sm" aria-hidden="true")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
.dropdown-item.d-flex.align-items-center .dropdown-item.d-flex.align-items-center
.flex-grow-1.mr-3 Status: .flex-grow-1.me-3 Status:
.dropdown(dropdown style="width: 65px;") .dropdown(dropdown style="width: 65px;")
button.online-offline.no-highlight.p-0.dropdown-toggle.no-arrow(dropdownToggle) button.online-offline.no-highlight.p-0.dropdown-toggle.no-arrow(dropdownToggle)
span.text-success(*ngIf="!hidden") online span.text-success(*ngIf="!hidden") online
span.text-muted(*ngIf="hidden") offline span.text-muted(*ngIf="hidden") offline
fa-icon.ml-2([icon]="cogIcon") fa-icon.ms-2([icon]="cogIcon")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
button.dropdown-item((click)="setStatus('online')") button.dropdown-item((click)="setStatus('online')")
fa-icon.mr-2.text-success([icon]="statusIcon" size="xs" [fixedWidth]="true") fa-icon.me-2.text-success([icon]="statusIcon" size="xs" [fixedWidth]="true")
| Online | Online
button.dropdown-item((click)="setStatus('invisible')") button.dropdown-item((click)="setStatus('invisible')")
fa-icon.mr-2.text-muted([icon]="statusIcon" size="xs" [fixedWidth]="true") fa-icon.me-2.text-muted([icon]="statusIcon" size="xs" [fixedWidth]="true")
| Show as Offline | Show as Offline
a.dropdown-item(routerLink="/account" (click)="dropdown.close()" tabindex) a.dropdown-item(routerLink="/account" (click)="dropdown.close()" tabindex)
| Account settings | Account settings
fa-icon.text-danger.ml-1(*ngIf="showAccountAlert" [icon]="alertIcon" aria-hidden="true") fa-icon.text-danger.ms-1(*ngIf="showAccountAlert" [icon]="alertIcon" aria-hidden="true")
.dropdown-divider .dropdown-divider
button.dropdown-item((click)="signOut.emit(); dropdown.close()") button.dropdown-item((click)="signOut.emit(); dropdown.close()")
| Sign out | Sign out
@@ -43,20 +43,20 @@ nav.navbar.navbar-expand.justify-content-end(role="navigation")
.text-muted(*ngIf="loading" style="font-size: 20px; padding: 10px 20px;") .text-muted(*ngIf="loading" style="font-size: 20px; padding: 10px 20px;")
fa-icon([icon]="spinnerIcon" [fixedWidth]="true" animation="spin") fa-icon([icon]="spinnerIcon" [fixedWidth]="true" animation="spin")
form.navbar-form.ml-2(*ngIf="!loading && !account") form.navbar-form.ms-2(*ngIf="!loading && !account")
.button-group.dropdown(dropdown) .button-group.dropdown(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle [disabled]="!!loadingError") button.btn.btn-default.dropdown-toggle(dropdownToggle [disabled]="!!loadingError")
| Sign in | Sign in
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
.dropdown-header(*ngIf="signUpProviders.length") .dropdown-header(*ngIf="signUpProviders.length")
| Sign in or sign up | Sign in or sign up
button.dropdown-item( button.dropdown-item(
*ngFor="let p of signUpProviders" (click)="signInTo(p)" title="Sign in using {{p.name}}") *ngFor="let p of signUpProviders" (click)="signInTo(p)" title="Sign in using {{p.name}}")
fa-icon.mr-1([icon]="icon(p.id)" [fixedWidth]="true") fa-icon.me-1([icon]="icon(p.id)" [fixedWidth]="true")
| {{p.name}} | {{p.name}}
.dropdown-header(*ngIf="signInProviders.length") .dropdown-header(*ngIf="signInProviders.length")
| Sign in only | Sign in only
button.dropdown-item.sign-in-only( button.dropdown-item.sign-in-only(
*ngFor="let p of signInProviders" (click)="signInTo(p)" title="Sign in using {{p.name}}") *ngFor="let p of signInProviders" (click)="signInTo(p)" title="Sign in using {{p.name}}")
fa-icon.mr-1([icon]="icon(p.id)" [fixedWidth]="true") fa-icon.me-1([icon]="icon(p.id)" [fixedWidth]="true")
| {{p.name}} | {{p.name}}
+11 -11
View File
@@ -3,14 +3,14 @@ ng-template(#notePopover)
cols="20" rows="8" agAutoFocus [(ngModel)]="note" (keydown.escape)="blur()" (blur)="blur()") cols="20" rows="8" agAutoFocus [(ngModel)]="note" (keydown.escape)="blur()" (blur)="blur()")
ng-template(#tooltip) ng-template(#tooltip)
.text-left.text-pre .text-start.text-pre
div(*ngIf="hasCounters") div(*ngIf="hasCounters")
span.text-muted spam: span.text-muted spam:
span.ml-1 {{counters?.spam || 0}} span.ms-1 {{counters?.spam || 0}}
span.text-muted.ml-1 swearing: span.text-muted.ms-1 swearing:
span.ml-1 {{counters?.swears || 0}} span.ms-1 {{counters?.swears || 0}}
span.text-muted.ml-1 timeouts: span.text-muted.ms-1 timeouts:
span.ml-1 {{counters?.timeouts || 0}} span.ms-1 {{counters?.timeouts || 0}}
div {{note}} div {{note}}
.btn-group.btn-group-xs.btn-group-shadow(*ngIf="check?.hgf?.bvc?.wer?.ngf") .btn-group.btn-group-xs.btn-group-shadow(*ngIf="check?.hgf?.bvc?.wer?.ngf")
@@ -22,11 +22,11 @@ ng-template(#tooltip)
fa-icon([icon]="moreIcon") fa-icon([icon]="moreIcon")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item((click)="report()") a.dropdown-item((click)="report()")
fa-icon.mr-1([icon]="flagIcon" [fixedWidth]="true") fa-icon.me-1([icon]="flagIcon" [fixedWidth]="true")
| Report | Report
h6.dropdown-header Other options h6.dropdown-header Other options
a.dropdown-item(*ngFor="let a of check.actions" (click)="modAction(a.action)") a.dropdown-item(*ngFor="let a of check.actions" (click)="modAction(a.action)")
fa-icon.mr-1.text-danger([icon]="dangerIcon" [fixedWidth]="true") fa-icon.me-1.text-danger([icon]="dangerIcon" [fixedWidth]="true")
| {{a.name}} | {{a.name}}
.btn-group( .btn-group(
@@ -46,7 +46,7 @@ ng-template(#tooltip)
.btn-group.dropdown(dropdown [tooltip]="muteTooltip") .btn-group.dropdown(dropdown [tooltip]="muteTooltip")
button.btn.btn-xs(dropdownToggle [ngClass]="className(mute)") button.btn.btn-xs(dropdownToggle [ngClass]="className(mute)")
fa-icon([icon]="muteIcon") fa-icon([icon]="muteIcon")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="setMute(0)") a.dropdown-item((click)="setMute(0)")
| clear #[b mute] | clear #[b mute]
a.dropdown-item((click)="setMute(-1)") a.dropdown-item((click)="setMute(-1)")
@@ -58,7 +58,7 @@ ng-template(#tooltip)
.btn-group.dropdown(dropdown [tooltip]="shadowTooltip") .btn-group.dropdown(dropdown [tooltip]="shadowTooltip")
button.btn.btn-xs(dropdownToggle [ngClass]="className(shadow)") button.btn.btn-xs(dropdownToggle [ngClass]="className(shadow)")
fa-icon([icon]="hideIcon") fa-icon([icon]="hideIcon")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item((click)="setShadow(0)") a.dropdown-item((click)="setShadow(0)")
| clear #[b shadow] | clear #[b shadow]
a.dropdown-item((click)="setShadow(-1)") a.dropdown-item((click)="setShadow(-1)")
@@ -72,4 +72,4 @@ ng-template(#tooltip)
.pony-mod-account(*ngIf="account") .pony-mod-account(*ngIf="account")
| {{account}} | {{account}}
span.text-smuted.ml-1 [{{country || '??'}}] span.text-smuted.ms-1 [{{country || '??'}}]
@@ -4,7 +4,7 @@ ng-template(#popover)
.small.text-muted.mb-1(*ngIf="notification.note") .small.text-muted.mb-1(*ngIf="notification.note")
| {{notification.note}} | {{notification.note}}
div div
button.btn.btn-xs.btn-outline-danger.float-right( button.btn.btn-xs.btn-outline-danger.float-end(
*ngIf="ignoreButton" (click)="ignore()" tooltip="Ignore this player") *ngIf="ignoreButton" (click)="ignore()" tooltip="Ignore this player")
fa-icon([icon]="banIcon") fa-icon([icon]="banIcon")
.notification-buttons .notification-buttons
+14 -14
View File
@@ -22,11 +22,11 @@
| Please install a different browser to be able to play the game. | Please install a different browser to be able to play the game.
.form-group(*ngIf="model.missingBirthdate && !birthdateSet && requestBirthdate") .form-group(*ngIf="model.missingBirthdate && !birthdateSet && requestBirthdate")
.alert.alert-warning.text-left(role="alert") .alert.alert-warning.text-start(role="alert")
label(for="birthdate") label(for="birthdate")
| Set your date of birth | Set your date of birth
date-picker([(date)]="birthdate") date-picker([(date)]="birthdate")
.mt-2.text-right .mt-2.text-end
button.btn.btn-default.px-4((click)="saveBirthdate()") Save button.btn.btn-default.px-4((click)="saveBirthdate()") Save
p.mb-0.mt-2 p.mb-0.mt-2
| Please fill-in your #[b date of birth] in order to not lose access to the game in future updates. | Please fill-in your #[b date of birth] in order to not lose access to the game in future updates.
@@ -36,7 +36,7 @@
button.btn.btn-lg.btn-success.text-ellipsis.flex-grow-1( button.btn.btn-lg.btn-success.text-ellipsis.flex-grow-1(
#playButton (click)="joining ? cancel() : play()" [disabled]="!canPlay && !joining") #playButton (click)="joining ? cancel() : play()" [disabled]="!canPlay && !joining")
div(*ngIf="joining") div(*ngIf="joining")
fa-icon.mr-1([icon]="spinnerIcon" animation="spin") fa-icon.me-1([icon]="spinnerIcon" animation="spin")
| Cancel | Cancel
div(*ngIf="!joining && server") div(*ngIf="!joining && server")
| #[strong {{label || 'Play'}}] on #[span {{server.name}}] | #[strong {{label || 'Play'}}] on #[span {{server.name}}]
@@ -48,21 +48,21 @@
.dropdown-menu.w-100(*dropdownMenu style="overflow: hidden") .dropdown-menu.w-100(*dropdownMenu style="overflow: hidden")
button.dropdown-item(*ngFor="let s of servers" (click)="server = s; playButton.focus()") button.dropdown-item(*ngFor="let s of servers" (click)="server = s; playButton.focus()")
div div
.float-right(style="position: relative;") .float-end(style="position: relative;")
.text-unsafe(*ngIf="s.offline") #[span.sr-only server] offline .text-unsafe(*ngIf="s.offline") #[span.visually-hidden server] offline
.text-muted(*ngIf="!s.offline") online #[span.sr-only players] ({{s.online}}) .text-muted(*ngIf="!s.offline") online #[span.visually-hidden players] ({{s.online}})
.flag.mr-2(*ngFor="let f of s.countryFlags" [ngClass]="'flag-' + f") .flag.me-2(*ngFor="let f of s.countryFlags" [ngClass]="'flag-' + f")
fa-icon.text-muted.mr-2(*ngIf="!hasFlag(s)" [icon]="getIcon(s)" size="lg") fa-icon.text-muted.me-2(*ngIf="!hasFlag(s)" [icon]="getIcon(s)" size="lg")
strong {{s.name}} strong {{s.name}}
.text-muted.text-wrap {{s.desc}} .text-muted.text-wrap {{s.desc}}
.form-group.text-left.text-muted.server-alert(*ngIf="server?.alert === '18+'") .form-group.text-start.text-muted.server-alert(*ngIf="server?.alert === '18+'")
fa-icon.float-left.p-2([icon]="warningIcon" size="2x") fa-icon.float-start.p-2([icon]="warningIcon" size="2x")
| By playing on this server you confirm that you are over 18 years old and you take no issue | By playing on this server you confirm that you are over 18 years old and you take no issue
| with seeing adult topics. | with seeing adult topics.
.form-group.text-left.text-info.server-alert(*ngIf="server?.alert === 'test'") .form-group.text-start.text-info.server-alert(*ngIf="server?.alert === 'test'")
fa-icon.float-left.p-2([icon]="infoIcon" size="2x") fa-icon.float-start.p-2([icon]="infoIcon" size="2x")
| Supporter test server: Here you can try experimental and unfinished features that we're working on. | Supporter test server: Here you can try experimental and unfinished features that we're working on.
| Keep in mind everything is subject to change. | Keep in mind everything is subject to change.
@@ -85,7 +85,7 @@
.form-group(*ngIf="isBrowserOutdated") .form-group(*ngIf="isBrowserOutdated")
.alert.alert-warning(role="alert") .alert.alert-warning(role="alert")
button.close.float-right((click)="dismissOutdatedBrowser()" aria-label="Close" style="font-size: 20px;") &times; button.close.float-end((click)="dismissOutdatedBrowser()" aria-label="Close" style="font-size: 20px;") &times;
| Your browser is outdated and is known to have issues running pixel.horse. | Your browser is outdated and is known to have issues running pixel.horse.
| Make sure you have latest version installed. | Make sure you have latest version installed.
@@ -115,7 +115,7 @@
.alert.alert-danger(role="alert") .alert.alert-danger(role="alert")
| {{error}} | {{error}}
.form-group.text-left.text-large(*ngIf="server") .form-group.text-start.text-large(*ngIf="server")
h5 Server rules h5 Server rules
p.text-muted.list-rules p.text-muted.list-rules
| {{server.desc}} | {{server.desc}}
@@ -1,4 +1,4 @@
.mx-auto.text-left.text-large(style="max-width: 400px;") .mx-auto.text-start.text-large(style="max-width: 400px;")
h5 General rules h5 General rules
ul.text-muted.list-rules ul.text-muted.list-rules
li(*ngFor="let r of rules") {{r}} li(*ngFor="let r of rules") {{r}}
+10 -10
View File
@@ -17,39 +17,39 @@
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item((click)="toggleIgnore()") button.dropdown-item((click)="toggleIgnore()")
fa-icon.mr-2([icon]="ignoreIcon" [fixedWidth]="true") fa-icon.me-2([icon]="ignoreIcon" [fixedWidth]="true")
| {{isIgnored(pony) ? 'Unignore player' : 'Ignore player'}} | {{isIgnored(pony) ? 'Unignore player' : 'Ignore player'}}
fa-icon.ml-1(*ngIf="isIgnored(pony)" [icon]="checkIcon") fa-icon.ms-1(*ngIf="isIgnored(pony)" [icon]="checkIcon")
button.dropdown-item((click)="hidePlayer(1)") button.dropdown-item((click)="hidePlayer(1)")
fa-icon.mr-2([icon]="hideIcon" [fixedWidth]="true") fa-icon.me-2([icon]="hideIcon" [fixedWidth]="true")
| Hide player #[span.text-muted (24 hours)] | Hide player #[span.text-muted (24 hours)]
button.dropdown-item((click)="hidePlayer(0)") button.dropdown-item((click)="hidePlayer(0)")
fa-icon.mr-2([icon]="hideIcon" [fixedWidth]="true") fa-icon.me-2([icon]="hideIcon" [fixedWidth]="true")
| Hide player #[span.text-muted (permanent)] | Hide player #[span.text-muted (permanent)]
.dropdown-divider .dropdown-divider
button.dropdown-item((click)="sendMessageTo()") button.dropdown-item((click)="sendMessageTo()")
fa-icon.mr-2([icon]="messageIcon" [fixedWidth]="true") fa-icon.me-2([icon]="messageIcon" [fixedWidth]="true")
| Send whisper | Send whisper
button.dropdown-item(*ngIf="!isFriend(pony)" (click)="addFriend()") button.dropdown-item(*ngIf="!isFriend(pony)" (click)="addFriend()")
fa-icon.mr-2.text-success([icon]="addFriendIcon" [fixedWidth]="true") fa-icon.me-2.text-success([icon]="addFriendIcon" [fixedWidth]="true")
| Send friend request | Send friend request
div(*ngIf="isFriend(pony)" style="position: relative;") div(*ngIf="isFriend(pony)" style="position: relative;")
button.dropdown-item((click)="removingFriend = true; $event.stopPropagation()") button.dropdown-item((click)="removingFriend = true; $event.stopPropagation()")
fa-icon.mr-2.text-danger([icon]="removeFriendIcon" [fixedWidth]="true") fa-icon.me-2.text-danger([icon]="removeFriendIcon" [fixedWidth]="true")
| Remove from friends | Remove from friends
.remove-confirmation.px-2.d-flex.justify-content-center(*ngIf="removingFriend") .remove-confirmation.px-2.d-flex.justify-content-center(*ngIf="removingFriend")
button.btn.btn-sm.btn-outline-success.flex-grow-1((click)="removingFriend = false; $event.stopPropagation()") button.btn.btn-sm.btn-outline-success.flex-grow-1((click)="removingFriend = false; $event.stopPropagation()")
| Cancel | Cancel
button.btn.btn-sm.btn-outline-danger.flex-grow-1.ml-1((click)="removeFriend()") button.btn.btn-sm.btn-outline-danger.flex-grow-1.ms-1((click)="removeFriend()")
| Confirm remove | Confirm remove
div(*ngIf="canInviteToSupporterServers") div(*ngIf="canInviteToSupporterServers")
h6.dropdown-header Supporter options h6.dropdown-header Supporter options
button.dropdown-item((click)="inviteToSupporterServers()") button.dropdown-item((click)="inviteToSupporterServers()")
fa-icon.mr-2.text-success([icon]="starIcon" [fixedWidth]="true") fa-icon.me-2.text-success([icon]="starIcon" [fixedWidth]="true")
| Invite to supporter servers | Invite to supporter servers
fa-icon.ml-1(*ngIf="isInvitedToSupporterServers" [icon]="checkIcon") fa-icon.ms-1(*ngIf="isInvitedToSupporterServers" [icon]="checkIcon")
.btn-group.btn-group-shadow(*ngIf="canInviteToParty || canRemoveFromParty || canPromoteToLeader") .btn-group.btn-group-shadow(*ngIf="canInviteToParty || canRemoveFromParty || canPromoteToLeader")
button.btn.btn-xs.btn-default(*ngIf="canInviteToParty" (click)="inviteToParty()" tooltip="Invite to party") button.btn.btn-xs.btn-default(*ngIf="canInviteToParty" (click)="inviteToParty()" tooltip="Invite to party")
@@ -11,40 +11,40 @@ ng-template(#actionsModal)
.dropdown(#dropdown="ag-dropdown" dropdown autoClose="outsideClick" [hookToCanvas]="true") .dropdown(#dropdown="ag-dropdown" dropdown autoClose="outsideClick" [hookToCanvas]="true")
button.game-button.dropdown-toggle.no-arrow(dropdownToggle (click)="false" title="Settings") button.game-button.dropdown-toggle.no-arrow(dropdownToggle (click)="false" title="Settings")
fa-icon([icon]="cogIcon" [fixedWidth]="true") fa-icon([icon]="cogIcon" [fixedWidth]="true")
.dropdown-menu.dropdown-menu-right.settings-box-menu(*dropdownMenu) .dropdown-menu.dropdown-menu-end.settings-box-menu(*dropdownMenu)
.dropdown-header.d-flex.justify-content-between.mb-1 .dropdown-header.d-flex.justify-content-between.mb-1
span {{server}} span {{server}}
span.clock-display {{time}} span.clock-display {{time}}
.dropdown-item.d-flex.mb-1 .dropdown-item.d-flex.mb-1
fa-icon.mr-2([icon]="searchIcon" [fixedWidth]="true") fa-icon.me-2([icon]="searchIcon" [fixedWidth]="true")
.flex-grow-1 Scale (x{{scale}}) .flex-grow-1 Scale (x{{scale}})
button.btn.btn-xs.btn-outline-secondary((click)="zoomOut()" aria-label="Zoom out") button.btn.btn-xs.btn-outline-secondary((click)="zoomOut()" aria-label="Zoom out")
fa-icon([icon]="minusIcon" [fixedWidth]="true") fa-icon([icon]="minusIcon" [fixedWidth]="true")
button.btn.btn-xs.btn-outline-secondary.ml-2((click)="zoomIn()" aria-label="Zoom in") button.btn.btn-xs.btn-outline-secondary.ms-2((click)="zoomIn()" aria-label="Zoom in")
fa-icon([icon]="plusIcon" [fixedWidth]="true") fa-icon([icon]="plusIcon" [fixedWidth]="true")
.dropdown-item.dropdown-item-static.mb-1 .dropdown-item.dropdown-item-static.mb-1
a((click)="toggleVolume()" title="Toggle sound") a((click)="toggleVolume()" title="Toggle sound")
fa-icon([icon]="volumeIcon" [fixedWidth]="true") fa-icon([icon]="volumeIcon" [fixedWidth]="true")
//.flex-grow-1 Volume //.flex-grow-1 Volume
slider-bar([(value)]="volume" [step]="1" (started)="volumeStarted()") slider-bar([(value)]="volume" [step]="1" (started)="volumeStarted()")
.text-muted.text-right(*ngIf="track" style="margin-top: -5px;") .text-muted.text-end(*ngIf="track" style="margin-top: -5px;")
small small
| playing: #[b {{track}}] | playing: #[b {{track}}]
a.text-muted.ml-1((click)="nextTrack()" title="Next track") a.text-muted.ms-1((click)="nextTrack()" title="Next track")
fa-icon([icon]="forwardIcon" [fixedWidth]="true") fa-icon([icon]="forwardIcon" [fixedWidth]="true")
a.dropdown-item((click)="unhideAllHiddenPlayers()").mb-1 a.dropdown-item((click)="unhideAllHiddenPlayers()").mb-1
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true") fa-icon.me-2([icon]="emptyIcon" [fixedWidth]="true")
| Unhide players (temporary) | Unhide players (temporary)
a.dropdown-item((click)="openSettings()").mb-1 a.dropdown-item((click)="openSettings()").mb-1
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true") fa-icon.me-2([icon]="emptyIcon" [fixedWidth]="true")
| Settings | Settings
a.dropdown-item((click)="openActions()").mb-1 a.dropdown-item((click)="openActions()").mb-1
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true") fa-icon.me-2([icon]="emptyIcon" [fixedWidth]="true")
| Actions | Actions
//-a.dropdown-item((click)="openInvites()" *ngIf="hasInvites") //-a.dropdown-item((click)="openInvites()" *ngIf="hasInvites")
fa-icon.mr-2([icon]="emptyIcon" [fixedWidth]="true") fa-icon.me-2([icon]="emptyIcon" [fixedWidth]="true")
| Manage invites | Manage invites
.dropdown-divider .dropdown-divider
a.dropdown-item((click)="leave()") a.dropdown-item((click)="leave()")
fa-icon.mr-2([icon]="signOutIcon" [fixedWidth]="true") fa-icon.me-2([icon]="signOutIcon" [fixedWidth]="true")
| Leave | Leave
@@ -32,7 +32,7 @@
.form-group .form-group
label#graphics-quality-label Graphics quality label#graphics-quality-label Graphics quality
div div
slider-bar.mr-2.mb-2( slider-bar.me-2.mb-2(
[(value)]="browser.graphicsQuality" [min]="0" [max]="maxGraphicsQuality" [step]="1" [(value)]="browser.graphicsQuality" [min]="0" [max]="maxGraphicsQuality" [step]="1"
style="max-width: 300px" labelledBy="graphics-quality-label") style="max-width: 300px" labelledBy="graphics-quality-label")
| {{graphicsQualityText}} | {{graphicsQualityText}}
@@ -82,14 +82,14 @@
.form-group .form-group
label#chatlog-opacity-label Chatlog background opacity label#chatlog-opacity-label Chatlog background opacity
div div
slider-bar.mr-2( slider-bar.me-2(
[(value)]="account.chatlogOpacity" style="max-width: 300px" labelledBy="chatlog-opacity-label") [(value)]="account.chatlogOpacity" style="max-width: 300px" labelledBy="chatlog-opacity-label")
| {{(account.chatlogOpacity / 100) | percent}} | {{(account.chatlogOpacity / 100) | percent}}
small.form-text.text-muted.mt-0 Changes chatlog background to make it more readable or less obtrusive. small.form-text.text-muted.mt-0 Changes chatlog background to make it more readable or less obtrusive.
.form-group .form-group
label#chatlog-range-label Chatlog range label#chatlog-range-label Chatlog range
div div
slider-bar.mr-2( slider-bar.me-2(
[(value)]="account.chatlogRange" [min]="minChatlogRange" [max]="maxChatlogRange" [step]="1" [(value)]="account.chatlogRange" [min]="minChatlogRange" [max]="maxChatlogRange" [step]="1"
(valueChange)="updateChatlogRange($event)" (changed)="finishChatlogRange()" (valueChange)="updateChatlogRange($event)" (changed)="finishChatlogRange()"
style="max-width: 300px" labelledBy="chatlog-range-label") style="max-width: 300px" labelledBy="chatlog-range-label")
@@ -141,5 +141,5 @@
.flex-grow-1 .flex-grow-1
button.btn.btn-wide.btn-outline-secondary((click)="cancel()") button.btn.btn-wide.btn-outline-secondary((click)="cancel()")
| Cancel | Cancel
button.btn.btn-wide.btn-outline-secondary.ml-2((click)="ok()") button.btn.btn-wide.btn-outline-secondary.ms-2((click)="ok()")
| OK | OK
@@ -14,7 +14,7 @@
[style.border-bottom-color]="p.color" [style.border-bottom-color]="p.color"
title="Sign in using {{p.name}}") title="Sign in using {{p.name}}")
fa-icon([icon]="icon(p.id)" [fixedWidth]="true" size="lg") fa-icon([icon]="icon(p.id)" [fixedWidth]="true" size="lg")
.sr-only Sign in or sign up using {{p.name}} .visually-hidden Sign in or sign up using {{p.name}}
div(*ngIf="signInProviders.length") div(*ngIf="signInProviders.length")
.sign-in-heading .sign-in-heading
@@ -30,7 +30,7 @@
[style.border-bottom-color]="p.color" [style.border-bottom-color]="p.color"
title="Sign in using {{p.name}}") title="Sign in using {{p.name}}")
fa-icon([icon]="icon(p.id)" [fixedWidth]="true" size="lg") fa-icon([icon]="icon(p.id)" [fixedWidth]="true" size="lg")
.sr-only Sign in using {{p.name}} .visually-hidden Sign in using {{p.name}}
div(*ngIf="local") div(*ngIf="local")
div(*ngIf="mocks === undefined") div(*ngIf="mocks === undefined")
@@ -1,3 +1,3 @@
a.site-info(*ngIf="info" [href]="info.url" target="_blank" rel="noopener noreferrer") a.site-info(*ngIf="info" [href]="info.url" target="_blank" rel="noopener noreferrer")
fa-icon.mr-1([icon]="icon" [fixedWidth]="true" [style.color]="info.color" size="lg") fa-icon.me-1([icon]="icon" [fixedWidth]="true" [style.color]="info.color" size="lg")
b {{info.name}} b {{info.name}}
@@ -29,11 +29,11 @@ $bar-border-radius: $bar-height * 0.5;
background: darken($slider-bg, 20%); background: darken($slider-bg, 20%);
.slider-bar-fill { .slider-bar-fill {
background: darken($progress-bg, 20%); background: darken($slider-fill, 20%);
} }
.slider-bar-control { .slider-bar-control {
background: darken(theme-color('default'), 20%); background: darken($default, 20%);
} }
} }
} }
@@ -66,7 +66,7 @@ $bar-border-radius: $bar-height * 0.5;
width: $bar-control-size; width: $bar-control-size;
height: $bar-control-size; height: $bar-control-size;
border-radius: 50%; border-radius: 50%;
background: theme-color('default'); background: $default;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5); box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
:host:focus & { :host:focus & {
@@ -2,6 +2,6 @@
button.game-button.dropdown-toggle.no-arrow(dropdownToggle title="Swap") button.game-button.dropdown-toggle.no-arrow(dropdownToggle title="Swap")
fa-icon([icon]="swapIcon" [fixedWidth]="true") fa-icon([icon]="swapIcon" [fixedWidth]="true")
fa-icon.timer-icon([icon]="timerIcon" [style.display]="timeout ? 'block' : 'none'") fa-icon.timer-icon([icon]="timerIcon" [style.display]="timeout ? 'block' : 'none'")
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
portrait-box([hidden]="!previewInfo" [pony]="previewInfo" size="medium" style="position: absolute; top: 5px; left: -80px;") portrait-box([hidden]="!previewInfo" [pony]="previewInfo" size="medium" style="position: absolute; top: 5px; left: -80px;")
character-list((selectCharacter)="swapPony($event)" (close)="dropdown.close()" (previewCharacter)="preview($event)" [inGame]="true") character-list((selectCharacter)="swapPony($event)" (close)="dropdown.close()" (previewCharacter)="preview($event)" [inGame]="true")
@@ -1,4 +1,4 @@
a.btn.btn-lg.btn-pt.btn-outline-primary.btn-block.mb-2( a.btn.btn-lg.btn-pt.btn-outline-primary.d-block.w-100.mb-2(
*ngIf="enableVisitPTButton" (mouseenter)="pony.select()" (mouseout)="pony.reset()" [href]="ptLink" target="_blank" *ngIf="enableVisitPTButton" (mouseenter)="pony.select()" (mouseout)="pony.reset()" [href]="ptLink" target="_blank"
rel="noopener noreferrer") rel="noopener noreferrer")
.pt-logo .pt-logo
@@ -1,7 +1,7 @@
.tools-range { .tools-range {
width: 160px; width: 175px;
&.input-group-sm { &.input-group-sm {
width: 140px; width: 165px;
} }
} }
@@ -1,35 +1,35 @@
ng-template(#shareLinkPopover) ng-template(#shareLinkPopover)
div div
span.close.ml-2((click)="shareLinkOpen = false") &times; span.close.ms-2((click)="shareLinkOpen = false") &times;
| {{shareLink}} | {{shareLink}}
.tools-animation.mb-5 .tools-animation.mb-5
.d-flex(*ngIf="loaded") .d-flex(*ngIf="loaded")
character-preview([pony]="info" [state]="state" [scale]="scale" style="height: 350px") character-preview([pony]="info" [state]="state" [scale]="scale" style="height: 350px")
.flex-grow-1.ml-2 .flex-grow-1.ms-2
.form-inline .form-inline
.form-group .form-group
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon" [fixedWidth]="true") fa-icon([icon]="homeIcon" [fixedWidth]="true")
.form-group .form-group
label.ml-2 pony: label.ms-2 pony:
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
| {{pony.name}} | {{pony.name}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let p of ponies" (click)="setPony(p)") {{p.name}} a.dropdown-item(*ngFor="let p of ponies" (click)="setPony(p)") {{p.name}}
button.btn.btn-default.ml-1((click)="reloadPonies()" title="Reload ponies") button.btn.btn-default.ms-1((click)="reloadPonies()" title="Reload ponies")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.form-group .form-group
label.ml-2 scale: label.ms-2 scale:
scale-picker.ml-1([(scale)]="scale") scale-picker.ms-1([(scale)]="scale")
//-.form-group //-.form-group
button.btn.ml-1(btnCheckbox [(ngModel)]="flip" (change)="update()" [btnHighlight]="flip") button.btn.ms-1(btnCheckbox [(ngModel)]="flip" (change)="update()" [btnHighlight]="flip")
fa-icon([icon]="rightIcon" [fixedWidth]="true") fa-icon([icon]="rightIcon" [fixedWidth]="true")
.form-group .form-group
label.ml-2 mode: label.ms-2 mode:
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
| {{mode}} | {{mode}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -42,34 +42,34 @@ ng-template(#shareLinkPopover)
.from-group.d-flex .from-group.d-flex
button.btn.btn-default((click)="playing = false; frame = 0;" title="Stop") button.btn.btn-default((click)="playing = false; frame = 0;" title="Stop")
fa-icon([icon]="stopIcon" [fixedWidth]="true") fa-icon([icon]="stopIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((click)="playing = !playing" [title]="playing ? 'Pause' : 'Play'") button.btn.btn-default.ms-1((click)="playing = !playing" [title]="playing ? 'Pause' : 'Play'")
fa-icon([icon]="playing ? pauseIcon : playIcon" [fixedWidth]="true") fa-icon([icon]="playing ? pauseIcon : playIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((click)="replay()" [disabled]="!playing" title="Replay") button.btn.btn-default.ms-1((click)="replay()" [disabled]="!playing" title="Replay")
fa-icon([icon]="replayIcon" [fixedWidth]="true") fa-icon([icon]="replayIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((mousedown)="prevFrame()" [disabled]="playing" title="Prev frame") button.btn.btn-default.ms-1((mousedown)="prevFrame()" [disabled]="playing" title="Prev frame")
fa-icon([icon]="prevIcon" [fixedWidth]="true") fa-icon([icon]="prevIcon" [fixedWidth]="true")
input.form-control.ml-1( input.form-control.ms-1(
[(ngModel)]="frame" [disabled]="playing" type="number" placeholder="frame" style="width: 100px;" [(ngModel)]="frame" [disabled]="playing" type="number" placeholder="frame" style="width: 100px;"
min="0" step="1") min="0" step="1")
button.btn.btn-default.ml-1((click)="nextFrame()" [disabled]="playing" title="Next frame") button.btn.btn-default.ms-1((click)="nextFrame()" [disabled]="playing" title="Next frame")
fa-icon([icon]="nextIcon" [fixedWidth]="true") fa-icon([icon]="nextIcon" [fixedWidth]="true")
.input-group.ml-1(style="width: 250px;") .input-group.ms-1(style="width: 260px;")
input.form-control([(ngModel)]="animation.name" (change)="update(); sortAnimations()" [disabled]="animation.builtin") input.form-control([(ngModel)]="animation.name" (change)="update(); sortAnimations()" [disabled]="animation.builtin")
.input-group-append.dropdown(dropdown) .input-group-append.dropdown(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item(*ngFor="let a of animations" (click)="selectAnimation(a)") a.dropdown-item(*ngFor="let a of animations" (click)="selectAnimation(a)")
| {{a.name}} | {{a.name}}
button.btn.ml-1(btnCheckbox [(ngModel)]="switch" (change)="update()" [btnHighlight]="switch" button.btn.ms-1(btnCheckbox [(ngModel)]="switch" (change)="update()" [btnHighlight]="switch"
title="Switch close and far legs") title="Switch close and far legs")
fa-icon([icon]="switchIcon" [fixedWidth]="true") fa-icon([icon]="switchIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((click)="newAnimation()" title="New Animation") button.btn.btn-default.ms-1((click)="newAnimation()" title="New Animation")
fa-icon([icon]="fileIcon" [fixedWidth]="true") fa-icon([icon]="fileIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((click)="duplicateAnimation()" title="Duplicate Animation") button.btn.btn-default.ms-1((click)="duplicateAnimation()" title="Duplicate Animation")
fa-icon([icon]="copyIcon" [fixedWidth]="true") fa-icon([icon]="copyIcon" [fixedWidth]="true")
button.btn.btn-danger.ml-1((click)="removeAnimation()" title="Delete Animation") button.btn.btn-danger.ms-1((click)="removeAnimation()" title="Delete Animation")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.form-inline .form-inline
@@ -78,9 +78,9 @@ ng-template(#shareLinkPopover)
(click)="share()" title="Share" [popover]="shareLinkPopover" [isOpen]="shareLinkOpen" (click)="share()" title="Share" [popover]="shareLinkPopover" [isOpen]="shareLinkOpen"
popover-enable="shareLink" popover-class="popover-wide") popover-enable="shareLink" popover-class="popover-wide")
fa-icon([icon]="shareIcon" [fixedWidth]="true") fa-icon([icon]="shareIcon" [fixedWidth]="true")
button.btn.btn-default.ml-1((click)="export()" title="Export") button.btn.btn-default.ms-1((click)="export()" title="Export")
fa-icon([icon]="codeIcon" [fixedWidth]="true") fa-icon([icon]="codeIcon" [fixedWidth]="true")
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default((click)="png()" title="Save as PNG") button.btn.btn-default((click)="png()" title="Save as PNG")
| PNG | PNG
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
@@ -88,7 +88,7 @@ ng-template(#shareLinkPopover)
a.dropdown-item((click)="png(2)") &times;2 a.dropdown-item((click)="png(2)") &times;2
a.dropdown-item((click)="png(3)") &times;3 a.dropdown-item((click)="png(3)") &times;3
a.dropdown-item((click)="png(4)") &times;4 a.dropdown-item((click)="png(4)") &times;4
.btn-group.ml-1(dropdown) .btn-group.ms-1(dropdown)
button.btn.btn-default((click)="gif()" title="Save as GIF") button.btn.btn-default((click)="gif()" title="Save as GIF")
| GIF | GIF
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
@@ -97,7 +97,7 @@ ng-template(#shareLinkPopover)
a.dropdown-item((click)="gif(3)") &times;3 a.dropdown-item((click)="gif(3)") &times;3
a.dropdown-item((click)="gif(4)") &times;4 a.dropdown-item((click)="gif(4)") &times;4
.btn.btn-warning.ml-1(*ngIf="animation.builtin" disabled) .btn.btn-warning.ms-1(*ngIf="animation.builtin" disabled)
| Changes to builtin animations aren't saved, duplicate it, to save the changes | Changes to builtin animations aren't saved, duplicate it, to save the changes
hr hr
@@ -105,20 +105,20 @@ ng-template(#shareLinkPopover)
.form-inline .form-inline
.form-group .form-group
label duration: label duration:
tools-range.ml-2([(ngModel)]="activeFrame.duration" (change)="update()" min="1" max="100" small="true") tools-range.ms-2([(ngModel)]="activeFrame.duration" (change)="update()" min="1" max="100" small="true")
.form-group .form-group
label.ml-2 fps: label.ms-2 fps:
tools-range.ml-2([(ngModel)]="animation.fps" (change)="update()" min="1" max="100" small="true") tools-range.ms-2([(ngModel)]="animation.fps" (change)="update()" min="1" max="100" small="true")
.form-group .form-group
button.btn.btn-sm.ml-1([(ngModel)]="animation.loop" btnCheckbox [btnHighlight]="animation.loop") button.btn.btn-sm.ms-1([(ngModel)]="animation.loop" btnCheckbox [btnHighlight]="animation.loop")
| loop | loop
.form-group(*ngIf="mode !== 'body'") .form-group(*ngIf="mode !== 'body'")
button.btn.btn-sm.ml-1([(ngModel)]="animation.dontOpenEyes" btnCheckbox [btnHighlight]="animation.dontOpenEyes") button.btn.btn-sm.ms-1([(ngModel)]="animation.dontOpenEyes" btnCheckbox [btnHighlight]="animation.dontOpenEyes")
| dontOpenEyes | dontOpenEyes
.form-group(*ngIf="mode !== 'body'") .form-group(*ngIf="mode !== 'body'")
button.btn.btn-sm.ml-1([(ngModel)]="animation.dontCloseMouth" btnCheckbox [btnHighlight]="animation.dontCloseMouth") button.btn.btn-sm.ms-1([(ngModel)]="animation.dontCloseMouth" btnCheckbox [btnHighlight]="animation.dontCloseMouth")
| dontCloseMouth | dontCloseMouth
.btn-group.ml-1(dropdown) .btn-group.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle title="Before animation") button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle title="Before animation")
| before: {{beforeAnimation?.name || 'none'}} | before: {{beforeAnimation?.name || 'none'}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -126,7 +126,7 @@ ng-template(#shareLinkPopover)
| none | none
a.dropdown-item(*ngFor="let a of bodyAnimations" (click)="selectBeforeAnimation(a)") a.dropdown-item(*ngFor="let a of bodyAnimations" (click)="selectBeforeAnimation(a)")
| {{a.name}} | {{a.name}}
.btn-group.ml-1(dropdown) .btn-group.ms-1(dropdown)
button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle title="After animation") button.btn.btn-sm.btn-default.dropdown-toggle(dropdownToggle title="After animation")
| after: {{afterAnimation?.name || 'none'}} | after: {{afterAnimation?.name || 'none'}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
@@ -138,16 +138,16 @@ ng-template(#shareLinkPopover)
.form-inline .form-inline
.form-group .form-group
label head offset: label head offset:
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.headX" (change)="update()" [min]="-20" [max]="20" [small]="true") [(ngModel)]="activeFrame.headX" (change)="update()" [min]="-20" [max]="20" [small]="true")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-default.btn-sm((click)="moveAllHead(-1, 0)" title="All frames left") button.btn.btn-default.btn-sm((click)="moveAllHead(-1, 0)" title="All frames left")
fa-icon([icon]="doubleLeftIcon" [fixedWidth]="true") fa-icon([icon]="doubleLeftIcon" [fixedWidth]="true")
button.btn.btn-default.btn-sm((click)="moveAllHead(1, 0)" title="All frames right") button.btn.btn-default.btn-sm((click)="moveAllHead(1, 0)" title="All frames right")
fa-icon([icon]="doubleRightIcon" [fixedWidth]="true") fa-icon([icon]="doubleRightIcon" [fixedWidth]="true")
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.headY" (change)="update()" [min]="-20" [max]="20" [small]="true" [vertical]="true") [(ngModel)]="activeFrame.headY" (change)="update()" [min]="-20" [max]="20" [small]="true" [vertical]="true")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-default.btn-sm((click)="moveAllHead(0, -1)" title="All frames up") button.btn.btn-default.btn-sm((click)="moveAllHead(0, -1)" title="All frames up")
fa-icon([icon]="doubleUpIcon" [fixedWidth]="true") fa-icon([icon]="doubleUpIcon" [fixedWidth]="true")
button.btn.btn-default.btn-sm((click)="moveAllHead(0, 1)" title="All frames down") button.btn.btn-default.btn-sm((click)="moveAllHead(0, 1)" title="All frames down")
@@ -156,16 +156,16 @@ ng-template(#shareLinkPopover)
.form-inline .form-inline
.form-group(*ngIf="mode === 'body'") .form-group(*ngIf="mode === 'body'")
label body offset: label body offset:
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.bodyX" (change)="update()" [min]="-50" [max]="50" [small]="true") [(ngModel)]="activeFrame.bodyX" (change)="update()" [min]="-50" [max]="50" [small]="true")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-default.btn-sm((click)="moveAllBody(-1, 0)" title="All frames left") button.btn.btn-default.btn-sm((click)="moveAllBody(-1, 0)" title="All frames left")
fa-icon([icon]="doubleLeftIcon" [fixedWidth]="true") fa-icon([icon]="doubleLeftIcon" [fixedWidth]="true")
button.btn.btn-default.btn-sm((click)="moveAllBody(1, 0)" title="All frames right") button.btn.btn-default.btn-sm((click)="moveAllBody(1, 0)" title="All frames right")
fa-icon([icon]="doubleRightIcon" [fixedWidth]="true") fa-icon([icon]="doubleRightIcon" [fixedWidth]="true")
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.bodyY" (change)="update()" [min]="-50" [max]="50" [small]="true" [vertical]="true") [(ngModel)]="activeFrame.bodyY" (change)="update()" [min]="-50" [max]="50" [small]="true" [vertical]="true")
.btn-group.ml-1 .btn-group.ms-1
button.btn.btn-default.btn-sm((click)="moveAllBody(0, -1)" title="All frames up") button.btn.btn-default.btn-sm((click)="moveAllBody(0, -1)" title="All frames up")
fa-icon([icon]="doubleUpIcon" [fixedWidth]="true") fa-icon([icon]="doubleUpIcon" [fixedWidth]="true")
button.btn.btn-default.btn-sm((click)="moveAllBody(0, 1)" title="All frames down") button.btn.btn-default.btn-sm((click)="moveAllBody(0, 1)" title="All frames down")
@@ -174,9 +174,9 @@ ng-template(#shareLinkPopover)
.form-inline .form-inline
.form-group(*ngIf="mode === 'body'") .form-group(*ngIf="mode === 'body'")
label shadow (x, size): label shadow (x, size):
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.shadowOffset" (change)="update()" [min]="-50" [max]="50" [small]="true") [(ngModel)]="activeFrame.shadowOffset" (change)="update()" [min]="-50" [max]="50" [small]="true")
tools-range.ml-2( tools-range.ms-2(
[(ngModel)]="activeFrame.shadowFrame" (change)="update()" [min]="-50" [max]="50" [small]="true") [(ngModel)]="activeFrame.shadowFrame" (change)="update()" [min]="-50" [max]="50" [small]="true")
hr hr
@@ -184,19 +184,19 @@ ng-template(#shareLinkPopover)
.form-inline .form-inline
.from-group.d-flex .from-group.d-flex
label frame: label frame:
button.btn.btn-sm.btn-default.ml-1((click)="addFrame()" title="Add new frame after current one") button.btn.btn-sm.btn-default.ms-1((click)="addFrame()" title="Add new frame after current one")
fa-icon([icon]="plusIcon" [fixedWidth]="true") fa-icon([icon]="plusIcon" [fixedWidth]="true")
button.btn.btn-sm.btn-default.ml-1((click)="duplicateFrame()" title="Duplicate frame and add after current one") button.btn.btn-sm.btn-default.ms-1((click)="duplicateFrame()" title="Duplicate frame and add after current one")
fa-icon([icon]="cloneIcon" [fixedWidth]="true") fa-icon([icon]="cloneIcon" [fixedWidth]="true")
button.btn.btn-sm.btn-default.ml-1((click)="moveFrameLeft()" [disabled]="frame === 0" title="Move current frame left") button.btn.btn-sm.btn-default.ms-1((click)="moveFrameLeft()" [disabled]="frame === 0" title="Move current frame left")
fa-icon([icon]="leftIcon" [fixedWidth]="true") fa-icon([icon]="leftIcon" [fixedWidth]="true")
button.btn.btn-sm.btn-default.ml-1((click)="moveFrameRight()" [disabled]="frame === (totalFrames - 1)" title="Move current frame right") button.btn.btn-sm.btn-default.ms-1((click)="moveFrameRight()" [disabled]="frame === (totalFrames - 1)" title="Move current frame right")
fa-icon([icon]="rightIcon" [fixedWidth]="true") fa-icon([icon]="rightIcon" [fixedWidth]="true")
button.btn.btn-sm.btn-default.ml-1((click)="removeFrame()" [disabled]="totalFrames < 2" title="Delete current frame") button.btn.btn-sm.btn-default.ms-1((click)="removeFrame()" [disabled]="totalFrames < 2" title="Delete current frame")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.tools-animation-timeline(*ngIf="loaded && mode === 'body'") .tools-animation-timeline(*ngIf="loaded && mode === 'body'")
.float-left .float-start
table.table.table-bordered.table-frames-header.table-sm table.table.table-bordered.table-frames-header.table-sm
thead thead
tr: th Frame (duration) tr: th Frame (duration)
@@ -207,12 +207,12 @@ ng-template(#shareLinkPopover)
tr: td.frame-cell Front close Leg tr: td.frame-cell Front close Leg
tr tr
td.frame-cell td.frame-cell
check-box.float-left([(checked)]="bodyAnimation.lockFrontLegs" (checkedChange)="update()" [icon]="lockIcon") check-box.float-start([(checked)]="bodyAnimation.lockFrontLegs" (checkedChange)="update()" [icon]="lockIcon")
| Front far Leg | Front far Leg
tr: td.frame-cell Back close Leg tr: td.frame-cell Back close Leg
tr tr
td.frame-cell td.frame-cell
check-box.float-left([(checked)]="bodyAnimation.lockBackLegs" (checkedChange)="update()" [icon]="lockIcon") check-box.float-start([(checked)]="bodyAnimation.lockBackLegs" (checkedChange)="update()" [icon]="lockIcon")
| Back far Leg | Back far Leg
tr: td.frame-cell Body tr: td.frame-cell Body
tr: td.frame-cell Wing tr: td.frame-cell Wing
@@ -223,7 +223,7 @@ ng-template(#shareLinkPopover)
tr tr
th(*ngFor="let f of bodyFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)") th(*ngFor="let f of bodyFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)")
| {{i + 1}} | {{i + 1}}
span.text-muted.ml-1 ({{f.duration || 1}}) span.text-muted.ms-1 ({{f.duration || 1}})
tbody tbody
tr tr
td(*ngFor="let f of bodyFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)") td(*ngFor="let f of bodyFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)")
@@ -279,7 +279,7 @@ ng-template(#shareLinkPopover)
(frameChange)="update()" (click)="selectFrame(i)") (frameChange)="update()" (click)="selectFrame(i)")
.tools-animation-timeline(*ngIf="loaded && mode === 'head'") .tools-animation-timeline(*ngIf="loaded && mode === 'head'")
.float-left .float-start
table.table.table-bordered.table-frames-header.table-sm table.table.table-bordered.table-frames-header.table-sm
thead thead
tr: th Frame (duration) tr: th Frame (duration)
@@ -288,7 +288,7 @@ ng-template(#shareLinkPopover)
tr: td.frame-cell Right eye tr: td.frame-cell Right eye
tr tr
td.frame-cell td.frame-cell
check-box.float-left([(checked)]="headAnimation.lockEyes" (checkedChange)="update()" [icon]="lockIcon") check-box.float-start([(checked)]="headAnimation.lockEyes" (checkedChange)="update()" [icon]="lockIcon")
| Left eye | Left eye
tr: td.frame-cell Mouth tr: td.frame-cell Mouth
.frames-view .frames-view
@@ -297,7 +297,7 @@ ng-template(#shareLinkPopover)
tr tr
th(*ngFor="let f of headFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)") th(*ngFor="let f of headFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)")
| {{i + 1}} | {{i + 1}}
span.text-muted.ml-1 ({{f.duration || 1}}) span.text-muted.ms-1 ({{f.duration || 1}})
tbody tbody
tr tr
td(*ngFor="let f of headFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)") td(*ngFor="let f of headFrames; index as i" [class.active]="isActive(i)" (click)="selectFrame(i)")
@@ -1,11 +1,11 @@
.d-flex.m-2 .d-flex.m-2
canvas.pixelart(#canvas width="1000" height="900") canvas.pixelart(#canvas width="1000" height="900")
.ml-2 .ms-2
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
button.btn.btn-default.ml-1((click)="toggleBg()") button.btn.btn-default.ms-1((click)="toggleBg()")
| Toggle BG | Toggle BG
.mt-2 .mt-2
fa-icon.supporter-1([icon]="starIcon" size="lg") fa-icon.supporter-1([icon]="starIcon" size="lg")
fa-icon.supporter-2.ml-1([icon]="starIcon" size="lg") fa-icon.supporter-2.ms-1([icon]="starIcon" size="lg")
fa-icon.supporter-3.ml-1([icon]="starIcon" size="lg") fa-icon.supporter-3.ms-1([icon]="starIcon" size="lg")
@@ -2,4 +2,4 @@
(agDrag)="drag($event)" agDragRelative="self" (contextmenu)="false" (agDrag)="drag($event)" agDragRelative="self" (contextmenu)="false"
style="position: relative; width: 1200px; height: 900px; margin: 20px; background: #222;") style="position: relative; width: 1200px; height: 900px; margin: 20px; background: #222;")
canvas(#canvas width="1200" height="900") canvas(#canvas width="1200" height="900")
.text-danger.ml-4(*ngIf="collided") collided .text-danger.ms-4(*ngIf="collided") collided
@@ -4,72 +4,72 @@
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
scale-picker.ml-1([(scale)]="scale" (scaleChange)="redraw()") scale-picker.ms-1([(scale)]="scale" (scaleChange)="redraw()")
.form-group .form-group
.input-group.ml-1(style="width: 200px;") .input-group.ms-1(style="width: 200px;")
input.form-control([(ngModel)]="name" placeholder="name") input.form-control([(ngModel)]="name" placeholder="name")
.input-group-append.dropdown(dropdown) .input-group-append.dropdown(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
.dropdown-menu.dropdown-menu-right(*dropdownMenu) .dropdown-menu.dropdown-menu-end(*dropdownMenu)
a.dropdown-item(*ngFor="let e of entities" (click)="setEntity(e)") a.dropdown-item(*ngFor="let e of entities" (click)="setEntity(e)")
| {{e.name}} | {{e.name}}
button.btn.btn-default.ml-1((click)="saveEntity()" [disabled]="!name") button.btn.btn-default.ms-1((click)="saveEntity()" [disabled]="!name")
fa-icon([icon]="saveIcon" [fixedWidth]="true") fa-icon([icon]="saveIcon" [fixedWidth]="true")
button.btn.btn-danger.ml-1((click)="setEntity(null)") button.btn.btn-danger.ms-1((click)="setEntity(null)")
fa-icon([icon]="eraserIcon" [fixedWidth]="true") fa-icon([icon]="eraserIcon" [fixedWidth]="true")
button.btn.btn-danger.ml-1((click)="removeEntity()") button.btn.btn-danger.ms-1((click)="removeEntity()")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.float-left.mt-1.mr-2 .float-start.mt-1.me-2
canvas(#canvas width=512 height=512 (mousedown)="mousedown($event)" (agDrag)="drag($event)" agDragRelative="self") canvas(#canvas width=512 height=512 (mousedown)="mousedown($event)" (agDrag)="drag($event)" agDragRelative="self")
.form-group.d-flex .form-group.d-flex
label.control-label.text-muted draw: label.control-label.text-muted draw:
custom-checkbox.ml-2([(checked)]="drawCenter" (checkedChange)="changed()") center custom-checkbox.ms-2([(checked)]="drawCenter" (checkedChange)="changed()") center
custom-checkbox.ml-2([(checked)]="drawSelection" (checkedChange)="changed()") selection custom-checkbox.ms-2([(checked)]="drawSelection" (checkedChange)="changed()") selection
custom-checkbox.ml-2([(checked)]="drawHold" (checkedChange)="changed()") as held custom-checkbox.ms-2([(checked)]="drawHold" (checkedChange)="changed()") as held
div div
.form-group(*ngFor="let p of parts") .form-group(*ngFor="let p of parts")
.form-inline(*ngIf="p.type === 'sprite'") .form-inline(*ngIf="p.type === 'sprite'")
label.text-muted sprite: label.text-muted sprite:
input.form-control.ml-1( input.form-control.ms-1(
[(ngModel)]="p.sprite" (input)="changed()" style="width: 200px;" [typeahead]="sprites" (typeaheadOnSelect)="changed()") [(ngModel)]="p.sprite" (input)="changed()" style="width: 200px;" [typeahead]="sprites" (typeaheadOnSelect)="changed()")
label.ml-1 x: label.ms-1 x:
input.form-control.input-sm.ml-1(type="number" [ngModel]="-p.x" (ngModelChange)="p.x = -$event" (input)="changed()" min="-1000" max="1000") input.form-control.input-sm.ms-1(type="number" [ngModel]="-p.x" (ngModelChange)="p.x = -$event" (input)="changed()" min="-1000" max="1000")
label.ml-1 y: label.ms-1 y:
input.form-control.input-sm.ml-1(type="number" [ngModel]="-p.y" (ngModelChange)="p.y = -$event" (input)="changed()" min="-1000" max="1000") input.form-control.input-sm.ms-1(type="number" [ngModel]="-p.y" (ngModelChange)="p.y = -$event" (input)="changed()" min="-1000" max="1000")
button.btn.btn-sm.btn-default.ml-1((click)="centerPart(p)" title="Center sprite") button.btn.btn-sm.btn-default.ms-1((click)="centerPart(p)" title="Center sprite")
fa-icon([icon]="crosshairsIcon" [fixedWidth]="true") fa-icon([icon]="crosshairsIcon" [fixedWidth]="true")
button.btn.btn-sm.btn-danger.ml-1((click)="removePart(p)" title="Remove part") button.btn.btn-sm.btn-danger.ms-1((click)="removePart(p)" title="Remove part")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
.form-inline(*ngIf="p.type === 'cover' || p.type === 'collider' || p.type === 'pickable'") .form-inline(*ngIf="p.type === 'cover' || p.type === 'collider' || p.type === 'pickable'")
label.text-muted {{p.type}}: label.text-muted {{p.type}}:
label.ml-1 x: label.ms-1 x:
input.form-control.input-sm.ml-1(type="number" [(ngModel)]="p.x" (input)="changed()" min="-1000" max="1000") input.form-control.input-sm.ms-1(type="number" [(ngModel)]="p.x" (input)="changed()" min="-1000" max="1000")
label.ml-1 y: label.ms-1 y:
input.form-control.input-sm.ml-1(type="number" [(ngModel)]="p.y" (input)="changed()" min="-1000" max="1000") input.form-control.input-sm.ms-1(type="number" [(ngModel)]="p.y" (input)="changed()" min="-1000" max="1000")
.form-inline(*ngIf="p.type === 'cover' || p.type === 'collider'") .form-inline(*ngIf="p.type === 'cover' || p.type === 'collider'")
label.ml-1 w: label.ms-1 w:
input.form-control.input-sm.ml-1(type="number" [(ngModel)]="p.w" (input)="changed()" min="1" max="1000") input.form-control.input-sm.ms-1(type="number" [(ngModel)]="p.w" (input)="changed()" min="1" max="1000")
label.ml-1 h: label.ms-1 h:
input.form-control.input-sm.ml-1(type="number" [(ngModel)]="p.h" (input)="changed()" min="1" max="1000") input.form-control.input-sm.ms-1(type="number" [(ngModel)]="p.h" (input)="changed()" min="1" max="1000")
button.btn.btn-sm.btn-danger.ml-1((click)="removePart(p)" title="Remove part") button.btn.btn-sm.btn-danger.ms-1((click)="removePart(p)" title="Remove part")
fa-icon([icon]="trashIcon" [fixedWidth]="true") fa-icon([icon]="trashIcon" [fixedWidth]="true")
hr hr
.form-group.form-inline .form-group.form-inline
button.btn.btn-sm.btn-default.ml-1((click)="addPart('sprite')") button.btn.btn-sm.btn-default.ms-1((click)="addPart('sprite')")
fa-icon.mr-1([icon]="plusIcon" [fixedWidth]="true") fa-icon.me-1([icon]="plusIcon" [fixedWidth]="true")
| Sprite | Sprite
button.btn.btn-sm.btn-default.ml-1((click)="addPart('cover')") button.btn.btn-sm.btn-default.ms-1((click)="addPart('cover')")
fa-icon.mr-1([icon]="plusIcon" [fixedWidth]="true") fa-icon.me-1([icon]="plusIcon" [fixedWidth]="true")
| Cover | Cover
button.btn.btn-sm.btn-default.ml-1((click)="addPart('collider')") button.btn.btn-sm.btn-default.ms-1((click)="addPart('collider')")
fa-icon.mr-1([icon]="plusIcon" [fixedWidth]="true") fa-icon.me-1([icon]="plusIcon" [fixedWidth]="true")
| Collider | Collider
button.btn.btn-sm.btn-default.ml-1((click)="addPart('pickable')") button.btn.btn-sm.btn-default.ms-1((click)="addPart('pickable')")
fa-icon.mr-1([icon]="plusIcon" [fixedWidth]="true") fa-icon.me-1([icon]="plusIcon" [fixedWidth]="true")
| Pickable | Pickable
@@ -4,14 +4,14 @@
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
label.ml-2 label.ms-2
scale-picker([(scale)]="scale" (scaleChange)="redraw()") scale-picker([(scale)]="scale" (scaleChange)="redraw()")
.form-group .form-group
label.control-label.ml-2 columns: label.control-label.ms-2 columns:
input.form-control.ml-1(type="number" [(ngModel)]="columns" (input)="redraw()" style="width: 80px;") input.form-control.ms-1(type="number" [(ngModel)]="columns" (input)="redraw()" style="width: 80px;")
.form-group .form-group
button.btn.btn-default.ml-2((click)="png()") PNG button.btn.btn-default.ms-2((click)="png()") PNG
canvas(#canvas) canvas(#canvas)
@@ -4,31 +4,31 @@
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
label.ml-2 map label.ms-2 map
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) {{selectedMap || 'main'}} button.btn.btn-default.dropdown-toggle(dropdownToggle) {{selectedMap || 'main'}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item(*ngFor="let m of maps" (click)="selectMap(m)") {{m || 'main'}} button.dropdown-item(*ngFor="let m of maps" (click)="selectMap(m)") {{m || 'main'}}
.form-group .form-group
label.ml-2 type label.ms-2 type
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) {{type}} button.btn.btn-default.dropdown-toggle(dropdownToggle) {{type}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
button.dropdown-item((click)="setType('regular')") regular button.dropdown-item((click)="setType('regular')") regular
button.dropdown-item((click)="setType('minimap')") minimap button.dropdown-item((click)="setType('minimap')") minimap
.form-group .form-group
label.ml-2 scale label.ms-2 scale
scale-picker.ml-1([(scale)]="scale" (scaleChange)="redraw()" [maxScale]="8") scale-picker.ms-1([(scale)]="scale" (scaleChange)="redraw()" [maxScale]="8")
.form-group .form-group
button.btn.btn-default.ml-2((click)="fetch()") Reload button.btn.btn-default.ms-2((click)="fetch()") Reload
.form-group .form-group
button.btn.btn-default.ml-2((click)="png()") PNG button.btn.btn-default.ms-2((click)="png()") PNG
.form-group .form-group
custom-checkbox.ml-2([(checked)]="grid" (checkedChange)="redraw()") Grid custom-checkbox.ms-2([(checked)]="grid" (checkedChange)="redraw()") Grid
canvas(#canvas) canvas(#canvas)
@@ -4,17 +4,17 @@
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
scale-picker.ml-1([(scale)]="scale" (scaleChange)="redraw()") scale-picker.ms-1([(scale)]="scale" (scaleChange)="redraw()")
.float-left.mr-2 .float-start.me-2
canvas(#canvas width=512 height=512) canvas(#canvas width=512 height=512)
.float-left .float-start
.form-group.form-inline .form-group.form-inline
label.text-muted sprite: label.text-muted sprite:
input.form-control.ml-1([(ngModel)]="spriteName" (change)="spriteChanged()" style="width: 200px;" input.form-control.ms-1([(ngModel)]="spriteName" (change)="spriteChanged()" style="width: 200px;"
[typeahead]="sprites" (typeaheadOnSelect)="spriteChanged()") [typeahead]="sprites" (typeaheadOnSelect)="spriteChanged()")
button.btn.btn-default.ml-1((click)="loadPalette()") button.btn.btn-default.ms-1((click)="loadPalette()")
| load palette | load palette
div div
@@ -2,8 +2,8 @@
.mb-2 .mb-2
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
button.btn.btn-default.ml-1((click)="run()") run test button.btn.btn-default.ms-1((click)="run()") run test
button.btn.btn-default.ml-1((click)="stats()") run stats button.btn.btn-default.ms-1((click)="stats()") run stats
button.btn.btn-default.ml-1(*ngFor="let test of tests" (click)="test.func()") {{test.name}} button.btn.btn-default.ms-1(*ngFor="let test of tests" (click)="test.func()") {{test.name}}
pre.rounded.p-3(style="color: white; background: #222;") pre.rounded.p-3(style="color: white; background: #222;")
| {{output}} | {{output}}
@@ -4,43 +4,43 @@
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
label.ml-2 sheets: label.ms-2 sheets:
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 200px;") button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 200px;")
| {{sheet.name}} | {{sheet.name}}
fa-icon.ml-1(*ngIf="sheet.file" [icon]="imageIcon") fa-icon.ms-1(*ngIf="sheet.file" [icon]="imageIcon")
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
div(*ngFor="let s of sheets") div(*ngFor="let s of sheets")
.dropdown-divider(*ngIf="s.spacer") .dropdown-divider(*ngIf="s.spacer")
a.dropdown-item((click)="setSheet(s)" *ngIf="!s.spacer") a.dropdown-item((click)="setSheet(s)" *ngIf="!s.spacer")
| {{s.name}} | {{s.name}}
fa-icon.ml-1(*ngIf="s.file" [icon]="imageIcon") fa-icon.ms-1(*ngIf="s.file" [icon]="imageIcon")
.form-group .form-group
label.ml-1 label.ms-1
scale-picker([(scale)]="scale" (scaleChange)="redraw()") scale-picker([(scale)]="scale" (scaleChange)="redraw()")
.form-group .form-group
button.btn.btn-default.ml-1((click)="redraw()") button.btn.btn-default.ms-1((click)="redraw()")
fa-icon([icon]="syncIcon" [fixedWidth]="true") fa-icon([icon]="syncIcon" [fixedWidth]="true")
.form-group .form-group
label.ml-2 rows: label.ms-2 rows:
input.form-control.ml-1(type="number" [(ngModel)]="rows" (input)="redraw()" style="width: 70px;") input.form-control.ms-1(type="number" [(ngModel)]="rows" (input)="redraw()" style="width: 70px;")
.form-group .form-group
label.ml-2 cols: label.ms-2 cols:
input.form-control.ml-1(type="number" [(ngModel)]="cols" (input)="redraw()" style="width: 70px;") input.form-control.ms-1(type="number" [(ngModel)]="cols" (input)="redraw()" style="width: 70px;")
.form-group .form-group
label.ml-2 pattern: label.ms-2 pattern:
input.form-control.ml-1(type="number" [(ngModel)]="pattern" (input)="redraw()" style="width: 70px;") input.form-control.ms-1(type="number" [(ngModel)]="pattern" (input)="redraw()" style="width: 70px;")
.form-group .form-group
button.btn.btn-default.ml-2((click)="png()") PNG button.btn.btn-default.ms-2((click)="png()") PNG
button.btn.btn-default.ml-1((click)="psd()") PSD button.btn.btn-default.ms-1((click)="psd()") PSD
button.btn.btn-default.ml-1((click)="allPSDs()") All PSDs button.btn.btn-default.ms-1((click)="allPSDs()") All PSDs
button.btn.btn-danger.ml-1(*ngIf="sheet.alert" disabled) {{sheet.alert}} button.btn.btn-danger.ms-1(*ngIf="sheet.alert" disabled) {{sheet.alert}}
.tools-sheet-offsets(#offsetsDiv [hidden]="!sheet.offsets") .tools-sheet-offsets(#offsetsDiv [hidden]="!sheet.offsets")
tools-offset( tools-offset(
@@ -2,7 +2,7 @@
.mb-3 .mb-3
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
button.btn.btn-default.ml-1((click)="logPositions()") button.btn.btn-default.ms-1((click)="logPositions()")
| log positions | log positions
.state-item-container .state-item-container
+25 -25
View File
@@ -23,25 +23,25 @@ ng-template(#modal)
.mb-3 .mb-3
.form-group.mb-2.d-flex.align-items-center .form-group.mb-2.d-flex.align-items-center
check-box([(checked)]="customOutlines") check-box([(checked)]="customOutlines")
check-box.ml-2([(checked)]="checked" [icon]="heartIcon") check-box.ms-2([(checked)]="checked" [icon]="heartIcon")
check-box.ml-2([(checked)]="checked" [icon]="lockIcon" [disabled]="true") check-box.ms-2([(checked)]="checked" [icon]="lockIcon" [disabled]="true")
label.ml-2 label.ms-2
| check box | check box
span.badge.badge-success.ml-2(*ngIf="checked") checked span.badge.badge-success.ms-2(*ngIf="checked") checked
.form-group .form-group
button.btn.btn-default(btnCheckbox [(ngModel)]="checked") btnCheckbox button.btn.btn-default(btnCheckbox [(ngModel)]="checked") btnCheckbox
.btn-group.ml-2(btnRadioGroup [(ngModel)]="radio") .btn-group.ms-2(btnRadioGroup [(ngModel)]="radio")
button.btn.btn-default(btnRadio="a") a button.btn.btn-default(btnRadio="a") a
button.btn.btn-default(btnRadio="b") b button.btn.btn-default(btnRadio="b") b
button.btn.btn-default(btnRadio="c") c button.btn.btn-default(btnRadio="c") c
span.ml-2 btnRadio: {{radio}} span.ms-2 btnRadio: {{radio}}
h3 Slider h3 Slider
.mb-3 .mb-3
.form-group .form-group
label label
span#slider-label music volume: span#slider-label music volume:
span.text-muted.ml-1 {{slider}} span.text-muted.ms-1 {{slider}}
.form-group .form-group
slider-bar([(value)]="slider" [step]="1" labelledBy="slider-label") slider-bar([(value)]="slider" [step]="1" labelledBy="slider-label")
.form-group .form-group
@@ -63,15 +63,15 @@ ng-template(#modal)
.mb-3 .mb-3
.form-group .form-group
fa-icon.supporter-1([icon]="starIcon" size="lg") fa-icon.supporter-1([icon]="starIcon" size="lg")
fa-icon.supporter-2.ml-1([icon]="starIcon" size="lg") fa-icon.supporter-2.ms-1([icon]="starIcon" size="lg")
fa-icon.supporter-3.ml-1([icon]="starIcon" size="lg") fa-icon.supporter-3.ms-1([icon]="starIcon" size="lg")
h3 External links h3 External links
.mb-3 .mb-3
.form-group .form-group
a(href="http://google.com/") should open in new tab a(href="http://google.com/") should open in new tab
.ml-5(style="width: 400px;") .ms-5(style="width: 400px;")
h3 Character preview h3 Character preview
.mb-3 .mb-3
character-preview([pony]="pony" name="Offline Pony" [tag]="selected.tag") character-preview([pony]="pony" name="Offline Pony" [tag]="selected.tag")
@@ -93,14 +93,14 @@ ng-template(#modal)
.dropdown-item aaa .dropdown-item aaa
.dropdown-item bbb .dropdown-item bbb
.dropdown-item ccc .dropdown-item ccc
.dropdown.ml-1(dropdown [autoClose]="autoCloseDropdown") .dropdown.ms-1(dropdown [autoClose]="autoCloseDropdown")
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
| 2nd one | 2nd one
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
.dropdown-item 111 .dropdown-item 111
.dropdown-item 222 .dropdown-item 222
.dropdown-item 333 .dropdown-item 333
.btn-group.ml-1(btnRadioGroup [(ngModel)]="autoCloseDropdown") .btn-group.ms-1(btnRadioGroup [(ngModel)]="autoCloseDropdown")
button.btn([btnRadio]="true" [btnHighlight]="autoCloseDropdown === true") true button.btn([btnRadio]="true" [btnHighlight]="autoCloseDropdown === true") true
button.btn([btnRadio]="false" [btnHighlight]="autoCloseDropdown === false") false button.btn([btnRadio]="false" [btnHighlight]="autoCloseDropdown === false") false
button.btn([btnRadio]="'outsideClick'" [btnHighlight]="autoCloseDropdown === 'outsideClick'") outsideClick button.btn([btnRadio]="'outsideClick'" [btnHighlight]="autoCloseDropdown === 'outsideClick'") outsideClick
@@ -117,7 +117,7 @@ ng-template(#modal)
tab(title="D" [disabled]="true") tab(title="D" [disabled]="true")
ng-template(tabContent) ddd ng-template(tabContent) ddd
.ml-5(style="width: 400px;") .ms-5(style="width: 400px;")
h3 Bitmap box h3 Bitmap box
.mb-3 .mb-3
bitmap-box([bitmap]="pony.cm" tool="brush" [color]="color" [width]="cmSize" [height]="cmSize") bitmap-box([bitmap]="pony.cm" tool="brush" [color]="color" [width]="cmSize" [height]="cmSize")
@@ -145,7 +145,7 @@ ng-template(#modal)
.form-group .form-group
party-list(style="position: absolute;") party-list(style="position: absolute;")
.ml-5(style="width: 400px") .ms-5(style="width: 400px")
h3 Pony box h3 Pony box
.mb-3 .mb-3
.form-group.py-4 .form-group.py-4
@@ -178,11 +178,11 @@ ng-template(#modal)
.mb-3 .mb-3
.form-group.d-flex .form-group.d-flex
portrait-box([pony]="pal") portrait-box([pony]="pal")
portrait-box.ml-2([pony]="pal" size="medium") portrait-box.ms-2([pony]="pal" size="medium")
portrait-box.ml-2([pony]="pal" size="small") portrait-box.ms-2([pony]="pal" size="small")
portrait-box.ml-2([pony]="pal" size="small" [noBorder]="true" [flip]="true") portrait-box.ms-2([pony]="pal" size="small" [noBorder]="true" [flip]="true")
.ml-5(style="width: 400px") .ms-5(style="width: 400px")
h3 Settings box h3 Settings box
.mb-3 .mb-3
div(style="position: relative") div(style="position: relative")
@@ -202,11 +202,11 @@ ng-template(#modal)
.mt-2 .mt-2
button.btn.btn-default((click)="addMessage(chatlog, 'some message')") button.btn.btn-default((click)="addMessage(chatlog, 'some message')")
| Add message | Add message
button.btn.btn-default.ml-1((click)="addMessage(chatlog, 'some 🍎 message')") button.btn.btn-default.ms-1((click)="addMessage(chatlog, 'some 🍎 message')")
| Add emote message | Add emote message
button.btn.btn-default.ml-1((click)="addWhisper(chatlog, 'some whisper message')") button.btn.btn-default.ms-1((click)="addWhisper(chatlog, 'some whisper message')")
| Add whisper | Add whisper
button.btn.ml-1((click)="spamChat(chatlog)" [btnHighlight]="spamChatInterval") button.btn.ms-1((click)="spamChat(chatlog)" [btnHighlight]="spamChatInterval")
| Spam chat | Spam chat
slider-bar([(value)]="chatlogOpacity" style="width: 300px") slider-bar([(value)]="chatlogOpacity" style="width: 300px")
span {{chatlogOpacity / 100 | percent}} span {{chatlogOpacity / 100 | percent}}
@@ -249,10 +249,10 @@ ng-template(#modal)
.text-muted(style="width: 100px") {{angle | number:'0.0-0'}} deg .text-muted(style="width: 100px") {{angle | number:'0.0-0'}} deg
.form-group.d-flex.align-items-center .form-group.d-flex.align-items-center
label.mb-0 horizontal tile height: label.mb-0 horizontal tile height:
.text-muted.ml-2 {{horizontalTileHeight}} px .text-muted.ms-2 {{horizontalTileHeight}} px
.form-group.d-flex.align-items-center .form-group.d-flex.align-items-center
label.mb-0 vertical tile height: label.mb-0 vertical tile height:
.text-muted.ml-2 {{verticalTileHeight}} px .text-muted.ms-2 {{verticalTileHeight}} px
tab(title="Virtual list") tab(title="Virtual list")
ng-template(tabContent) ng-template(tabContent)
@@ -279,7 +279,7 @@ ng-template(#modal)
div(style="margin: 50px;") div(style="margin: 50px;")
button.btn.btn-default((click)="virtualItems2.push({ name: 'An item ' + virtualItems2.length })") Add button.btn.btn-default((click)="virtualItems2.push({ name: 'An item ' + virtualItems2.length })") Add
button.btn.btn-default.ml-1((click)="virtualItems2.pop()") Remove button.btn.btn-default.ms-1((click)="virtualItems2.pop()") Remove
button.btn.btn-default.ml-1((click)="virtualItems2.push(virtualItems2.shift())") Move button.btn.btn-default.ms-1((click)="virtualItems2.push(virtualItems2.shift())") Move
#range-indicator #range-indicator
@@ -3,36 +3,36 @@
a.btn.btn-default(routerLink="/") a.btn.btn-default(routerLink="/")
fa-icon([icon]="homeIcon") fa-icon([icon]="homeIcon")
.form-group .form-group
label.control-label.ml-2 horizontal: label.control-label.ms-2 horizontal:
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 140px;") button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 140px;")
| {{horizontal}} | {{horizontal}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let f of fields" (click)="horizontal = f; redraw();") {{f}} a.dropdown-item(*ngFor="let f of fields" (click)="horizontal = f; redraw();") {{f}}
.form-group .form-group
label.control-label.ml-2 vertical: label.control-label.ms-2 vertical:
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 140px;") button.btn.btn-default.dropdown-toggle(dropdownToggle style="width: 140px;")
| {{vertical}} | {{vertical}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)
a.dropdown-item(*ngFor="let f of fields" (click)="vertical = f; redraw();") {{f}} a.dropdown-item(*ngFor="let f of fields" (click)="vertical = f; redraw();") {{f}}
.form-group .form-group
label.control-label.ml-2 coat: label.control-label.ms-2 coat:
color-picker.color-picker-inline.ml-1([(color)]="coat" (colorChange)="redraw()") color-picker.color-picker-inline.ms-1([(color)]="coat" (colorChange)="redraw()")
.form-group .form-group
label.control-label.ml-2 hair: label.control-label.ms-2 hair:
color-picker.color-picker-inline.ml-1([(color)]="hair" (colorChange)="redraw()") color-picker.color-picker-inline.ms-1([(color)]="hair" (colorChange)="redraw()")
.form-group .form-group
label.control-label.ml-2 just head label.control-label.ms-2 just head
check-box.check-box-inline.ml-1([(checked)]="justHead" (checkedChange)="redraw()") check-box.check-box-inline.ms-1([(checked)]="justHead" (checkedChange)="redraw()")
.form-group .form-group
label.control-label.ml-2 label.control-label.ms-2
.btn-group.dropdown.ml-1(dropdown) .btn-group.dropdown.ms-1(dropdown)
button.btn.btn-default.dropdown-toggle(dropdownToggle) button.btn.btn-default.dropdown-toggle(dropdownToggle)
| &times;{{scale}} | &times;{{scale}}
.dropdown-menu(*dropdownMenu) .dropdown-menu(*dropdownMenu)