Removed the old permission editor
This commit is contained in:
parent
fe130b5989
commit
5767430f79
18 changed files with 8 additions and 4971 deletions
|
@ -184,7 +184,6 @@ const loader_style = {
|
|||
"css/static/modal-poke.css",
|
||||
"css/static/modal-server.css",
|
||||
"css/static/modal-keyselect.css",
|
||||
"css/static/modal-permissions.css",
|
||||
"css/static/modal-group-assignment.css",
|
||||
"css/static/overlay-image-preview.css",
|
||||
"css/static/context_menu.css",
|
||||
|
|
|
@ -36,7 +36,6 @@ files=(
|
|||
"css/static/modal-newcomer.css"
|
||||
"css/static/modal-invite.css"
|
||||
"css/static/modal-keyselect.css"
|
||||
"css/static/modal-permissions.css"
|
||||
"css/static/modal-poke.css"
|
||||
"css/static/modal-query.css"
|
||||
"css/static/modal-server.css"
|
||||
|
|
|
@ -1,865 +0,0 @@
|
|||
@import "mixin";
|
||||
@import "properties";
|
||||
|
||||
.modal-body.modal-permission-editor {
|
||||
padding: 0!important;
|
||||
|
||||
display: flex!important;;
|
||||
flex-direction: column!important;;
|
||||
justify-content: stretch!important;;
|
||||
|
||||
width: 1000000em; /* get us some width */
|
||||
min-height: 20em; /* Set it here, so we dont have a inner modal scroll */
|
||||
|
||||
@include user-select(none);
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
padding: 0!important;
|
||||
|
||||
width: 100%;
|
||||
max-height: 90vh;
|
||||
min-height: 20em;
|
||||
height: 100000000px; /* enforce max height */
|
||||
}
|
||||
|
||||
.header {
|
||||
height: 4em;
|
||||
background-color: var(--modal-permissions-header-background);
|
||||
color: var(--modal-permissions-header-text);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
> .entry {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
text-align: center;
|
||||
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
}
|
||||
|
||||
.container > .left, .container > .right {
|
||||
max-height: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
> .header {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
> .body {
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.container >.right {
|
||||
z-index: 2; /* because the left container overlaps the right container once */
|
||||
|
||||
width: 75%;
|
||||
min-width: 30em;
|
||||
|
||||
background-color: var(--modal-permission-right);
|
||||
|
||||
/* DONE! */
|
||||
.header {
|
||||
> .entry {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
cursor: pointer;
|
||||
padding-bottom: 2px;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--modal-permissions-header-hover);
|
||||
|
||||
padding-bottom: 0;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
|
||||
margin-right: -10em;
|
||||
margin-left: -10em;
|
||||
margin-bottom: -.2em;
|
||||
bottom: 0;
|
||||
|
||||
height: 100%;
|
||||
width: calc(100% + 20em);
|
||||
|
||||
box-shadow: inset 0px -1.2em 3em -20px var(--modal-permissions-header-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--modal-permissions-header-selected);
|
||||
|
||||
padding-bottom: 0;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
|
||||
margin-right: -10em;
|
||||
margin-left: -10em;
|
||||
margin-bottom: -.2em;
|
||||
bottom: 0;
|
||||
|
||||
height: 100%;
|
||||
width: calc(100% + 20em);
|
||||
|
||||
box-shadow: inset 0px -1.2em 3em -20px var(--modal-permissions-header-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
min-height: 16em;
|
||||
|
||||
> .container { /* container permission editor */
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-height: 10em;
|
||||
min-width: 30em;
|
||||
|
||||
.permission-editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container >.left {
|
||||
width: 25%;
|
||||
min-width: 10em;
|
||||
min-height: 10em;
|
||||
overflow: hidden;
|
||||
|
||||
background-color: var(--modal-permission-left);
|
||||
|
||||
.header {
|
||||
font-weight: bold;
|
||||
|
||||
> .entry {
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
> * {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
min-height: 16em;
|
||||
|
||||
.container {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-height: 15em;
|
||||
overflow-y: auto;
|
||||
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* server group left list layout */
|
||||
.container-view-server-groups, .container-view-channel-groups, .container-view-channel-permissions, .container-view-client-channel-permissions, .container-view-client-channel-permissions {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.list-groups, .list-channel, .list-clients {
|
||||
color: var(--text);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
overflow: auto;
|
||||
@include chat-scrollbar-vertical();
|
||||
@include chat-scrollbar-horizontal();
|
||||
|
||||
width: 100%;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
.entries {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
height: max-content;
|
||||
|
||||
min-width: 100%;
|
||||
width: max-content;
|
||||
|
||||
.group, .channel, .client {
|
||||
padding-left: .25em;
|
||||
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--modal-permissions-entry-hover);
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: var(--modal-permissions-entry-selected);
|
||||
}
|
||||
|
||||
@include transition(background-color .25s ease-in-out);
|
||||
|
||||
.icon-container, .icon {
|
||||
align-self: center;
|
||||
margin-right: .25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-buttons {
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
height: 2.5em;
|
||||
width: 100%;
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
background-color: var(--modal-permissions-buttons-background);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--modal-permissions-buttons-hover);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: var(--modal-permissions-buttons-disabled);
|
||||
}
|
||||
|
||||
@include transition(background-color .25s ease-in-out);
|
||||
|
||||
img {
|
||||
width: 2.2em;
|
||||
height: 2.2em;
|
||||
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-view-server-groups {
|
||||
position: relative;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
$animation_length: .3s;
|
||||
.container-group-list {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
&.hidden {
|
||||
@include transform(translateX(-100%));
|
||||
}
|
||||
@include transition($animation_length ease-in-out);
|
||||
}
|
||||
|
||||
.container-client-list {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
.container-current-group {
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
background-color: var(--modal-permissions-current-group);
|
||||
color: var(--text);
|
||||
padding-left: .25em;
|
||||
|
||||
|
||||
height: 1.5em;
|
||||
font-size: 1.125em;
|
||||
|
||||
> .icon-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
height: 100%;
|
||||
margin-right: .25em;
|
||||
}
|
||||
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
height: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
@include transform(translateX(100%));
|
||||
}
|
||||
@include transition($animation_length ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
.container-view-client-permissions, .container-view-client-channel-permissions {
|
||||
.client-info {
|
||||
width: 100%;
|
||||
padding: .25em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-top: 2px solid var(--modal-permissions-seperator);
|
||||
}
|
||||
}
|
||||
|
||||
.container-view-client-channel-permissions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.container-seperator {
|
||||
width: 3px;
|
||||
height: unset!important;
|
||||
background-color: var(--modal-permissions-container-seperator)!important;
|
||||
}
|
||||
}
|
||||
|
||||
/* canvas permission editor */
|
||||
//TODO: Some styling needed
|
||||
.container-permissions-canvas {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
width: 100%;
|
||||
|
||||
.container-permissions {
|
||||
padding: .5em;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.permission-explorer {
|
||||
min-width: 750px;
|
||||
}
|
||||
|
||||
.switch {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
.column-name {
|
||||
align-self: center;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.entry-editor-container {
|
||||
@include chat-scrollbar-vertical();
|
||||
}
|
||||
}
|
||||
|
||||
/* html permission editor */
|
||||
.container-permissions-html {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
min-height: 10em;
|
||||
width: 100%;
|
||||
|
||||
.container-filter, .container-footer {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.container-filter {
|
||||
justify-content: stretch;
|
||||
height: 3em;
|
||||
|
||||
> * {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.button-toggle-clients {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
width: 16em;
|
||||
height: 2.5em;
|
||||
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.container-input {
|
||||
flex-grow: 5;
|
||||
flex-shrink: 1;
|
||||
|
||||
padding-top: 0!important;
|
||||
margin-bottom: 0!important;
|
||||
|
||||
height: 2.5em;
|
||||
|
||||
.bmd-label-floating {
|
||||
top: .5em;
|
||||
}
|
||||
|
||||
&.is-filled, &:focus-within {
|
||||
.bmd-label-floating {
|
||||
top: -.4em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-switchs {
|
||||
height: 2.5em;
|
||||
|
||||
margin-left: 1em;
|
||||
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
max-width: 10em;
|
||||
min-width: 5em;
|
||||
|
||||
color: var(--text);
|
||||
|
||||
> label {
|
||||
font-size: .75em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
|
||||
pointer-events: all;
|
||||
cursor: pointer;
|
||||
|
||||
.switch {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
a {
|
||||
padding-left: .25em;
|
||||
font-size: 1.1em;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.container-icon-select {
|
||||
position: relative;
|
||||
|
||||
height: 2.5em;
|
||||
|
||||
border-radius: .2em;
|
||||
margin-left: 1em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
|
||||
cursor: pointer;
|
||||
background-color: var(--modal-permissions-icon-select);
|
||||
border: 1px solid var(--modal-permissions-icon-select-border);
|
||||
|
||||
.icon-preview {
|
||||
height: 100%;
|
||||
width: 3em;
|
||||
|
||||
border: none;
|
||||
border-right: 1px solid var(--modal-permissions-icon-select-border);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
> div {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
> img {
|
||||
align-self: center;
|
||||
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
@include transition(border-color $button_hover_animation_time ease-in-out);
|
||||
}
|
||||
|
||||
.container-dropdown {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
height: 100%;
|
||||
width: 1.5em;
|
||||
|
||||
.button {
|
||||
text-align: center;
|
||||
|
||||
.arrow {
|
||||
border-color: var(--text);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
|
||||
top: calc(2.5em - 2px);
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
background-color: var(--modal-permissions-icon-select);
|
||||
border: 1px solid var(--modal-permissions-icon-select-border);
|
||||
border-radius: .2em 0 .2em .2em;
|
||||
|
||||
right: -1px;
|
||||
|
||||
.entry {
|
||||
padding: .5em;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--modal-permissions-icon-select-border);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--modal-permissions-icon-select-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-bottom-right-radius: 0;
|
||||
.dropdown {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--modal-permissions-icon-select-hover);
|
||||
border-color: var(--modal-permissions-icon-select-hover-border);
|
||||
|
||||
.icon-preview {
|
||||
border-color: var(--modal-permissions-icon-select-hover-border);
|
||||
}
|
||||
}
|
||||
|
||||
@include transition(border-color $button_hover_animation_time ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
.container-mode {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 5em;
|
||||
|
||||
&.container-mode-permissions {
|
||||
.container-permission-list {
|
||||
width: 100%;
|
||||
color: var(--text);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
min-height: 5em;
|
||||
|
||||
.entry {
|
||||
width: 100%;
|
||||
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
height: 2em;
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--modal-permissions-table-border);
|
||||
background-color: var(--modal-permissions-table-row-odd);
|
||||
|
||||
color: var(--modal-permissions-table-row-text);
|
||||
|
||||
@mixin fixed-column($name, $width) {
|
||||
.column-#{$name} {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: stretch;
|
||||
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
width: $width;
|
||||
|
||||
align-items: center;
|
||||
|
||||
padding-left: 1em;
|
||||
|
||||
border: none;
|
||||
border-right: 1px solid var(--modal-permissions-table-border);
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
max-width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include fixed-column(name, 6em);
|
||||
@include fixed-column(value, 6em);
|
||||
@include fixed-column(skip, 5em);
|
||||
@include fixed-column(negate, 5em);
|
||||
@include fixed-column(granted, 6em);
|
||||
|
||||
.column-name {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
.arrow {
|
||||
cursor: pointer;
|
||||
border-color: var(--modal-permissions-table-entry-active-text);
|
||||
}
|
||||
|
||||
.group-name {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.column-granted {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
|
||||
&.active {
|
||||
color: var(--modal-permissions-table-entry-active-text);
|
||||
}
|
||||
|
||||
&.group {
|
||||
color: var(--modal-permissions-table-entry-group-text);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input {
|
||||
color: var(--modal-permissions-table-input);
|
||||
|
||||
outline: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
|
||||
height: 1.5em;
|
||||
width: 5em; /* the column width minus one */
|
||||
|
||||
/* fix the column padding */
|
||||
padding-left: 1em;
|
||||
margin-left: -.5em; /* have a bit of space on both sides */
|
||||
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&:focus {
|
||||
border-bottom-color: var(--modal-permissions-table-input-focus);
|
||||
}
|
||||
@include transition(border-bottom-color $button_hover_animation_time ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
|
||||
min-height: 6em; /* TODO: Width */
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: stretch;
|
||||
|
||||
overflow-y: scroll;
|
||||
overflow-x: auto;
|
||||
|
||||
@include chat-scrollbar-vertical();
|
||||
@include chat-scrollbar-horizontal();
|
||||
|
||||
.entry {
|
||||
&.even {
|
||||
background-color: var(--modal-permissions-table-row-even);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--modal-permissions-table-row-hover);
|
||||
}
|
||||
/* We cant use this effect here because the odd/even effect would be a bit crazy then */
|
||||
//@include transition(background-color $button_hover_animation_time ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: var(--modal-permissions-table-header);
|
||||
color: var(--modal-permissions-table-header-text);
|
||||
|
||||
font-weight: bold;
|
||||
|
||||
.column-granted {
|
||||
margin-right: .5em; /* scroll bar */
|
||||
-moz-margin-end: 12px; /* moz scroll bar */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.container-mode-no-permissions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
|
||||
text-align: center;
|
||||
font-size: 2em;
|
||||
|
||||
color: var(--modal-permission-left);
|
||||
}
|
||||
}
|
||||
|
||||
.container-footer {
|
||||
justify-content: flex-end;
|
||||
margin-top: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-group-add {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
button {
|
||||
min-width: 6em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import {openBanList} from "tc-shared/ui/modal/ModalBanList";
|
|||
import {formatMessage} from "tc-shared/ui/frames/chat";
|
||||
import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration";
|
||||
import {spawnSettingsModal} from "tc-shared/ui/modal/ModalSettings";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permissionv2/ModalPermissionEditor";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
||||
|
||||
/*
|
||||
function initialize_sounds(event_registry: Registry<ClientGlobalControlEvents>) {
|
||||
|
|
|
@ -34,7 +34,7 @@ import {spawnFileTransferModal} from "tc-shared/ui/modal/transfer/ModalFileTrans
|
|||
import {MenuEntryType, spawn_context_menu} from "tc-shared/ui/elements/ContextMenu";
|
||||
import {copy_to_clipboard} from "tc-shared/utils/helpers";
|
||||
import ContextMenuEvent = JQuery.ContextMenuEvent;
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permissionv2/ModalPermissionEditor";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
||||
import {spawnGroupCreate} from "tc-shared/ui/modal/ModalGroups";
|
||||
|
||||
/* required import for init */
|
||||
|
|
|
@ -27,7 +27,7 @@ import { ClientEntry as ClientEntryView } from "./tree/Client";
|
|||
import * as React from "react";
|
||||
import {ChannelTreeEntry, ChannelTreeEntryEvents} from "tc-shared/ui/TreeEntry";
|
||||
import {spawnClientVolumeChange, spawnMusicBotVolumeChange} from "tc-shared/ui/modal/ModalChangeVolumeNew";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permissionv2/ModalPermissionEditor";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
||||
|
||||
export enum ClientType {
|
||||
CLIENT_VOICE,
|
||||
|
|
|
@ -23,7 +23,7 @@ import * as loader from "tc-loader";
|
|||
import {formatMessage} from "tc-shared/ui/frames/chat";
|
||||
import {control_bar_instance} from "tc-shared/ui/frames/control-bar";
|
||||
import {icon_cache_loader, IconManager, LocalIcon} from "tc-shared/file/Icons";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permissionv2/ModalPermissionEditor";
|
||||
import {spawnPermissionEditorModal} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
||||
|
||||
export interface HRItem { }
|
||||
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import {GroupedPermissions, PermissionInfo, PermissionValue} from "tc-shared/permission/PermissionManager";
|
||||
import PermissionType from "tc-shared/permission/PermissionType";
|
||||
|
||||
export enum PermissionEditorMode {
|
||||
VISIBLE,
|
||||
NO_PERMISSION,
|
||||
UNSET
|
||||
}
|
||||
|
||||
export abstract class AbstractPermissionEditor {
|
||||
protected _permissions: GroupedPermissions[];
|
||||
protected _listener_update: () => any;
|
||||
protected _listener_change: ChangeListener = () => Promise.resolve();
|
||||
protected _toggle_callback: () => string;
|
||||
|
||||
icon_resolver: (id: number) => Promise<HTMLImageElement>;
|
||||
icon_selector: (current_id: number) => Promise<number>;
|
||||
|
||||
protected constructor() {}
|
||||
|
||||
abstract set_mode(mode: PermissionEditorMode);
|
||||
|
||||
abstract initialize(permissions: GroupedPermissions[]);
|
||||
abstract html_tag() : JQuery;
|
||||
abstract set_permissions(permissions?: PermissionValue[]);
|
||||
abstract set_hidden_permissions(permissions: PermissionType[]);
|
||||
|
||||
set_listener(listener?: ChangeListener) {
|
||||
this._listener_change = listener || (() => Promise.resolve());
|
||||
}
|
||||
|
||||
set_listener_update(listener?: () => any) { this._listener_update = listener; }
|
||||
trigger_update() { if(this._listener_update) this._listener_update(); }
|
||||
|
||||
abstract set_toggle_button(callback: () => string, initial: string);
|
||||
}
|
||||
|
||||
export interface PermissionEntry {
|
||||
tag: JQuery;
|
||||
tag_value: JQuery;
|
||||
tag_grant: JQuery;
|
||||
tag_flag_negate: JQuery;
|
||||
tag_flag_skip: JQuery;
|
||||
|
||||
id: number;
|
||||
filter: string;
|
||||
is_bool: boolean;
|
||||
|
||||
}
|
||||
|
||||
export interface ChangedPermissionValue {
|
||||
remove: boolean; /* if set remove the set permission (value or granted) */
|
||||
|
||||
granted?: number;
|
||||
value?: number;
|
||||
|
||||
flag_skip?: boolean;
|
||||
flag_negate?: boolean;
|
||||
}
|
||||
|
||||
export type ChangeListener = (permission: PermissionInfo, value?: ChangedPermissionValue) => Promise<void>;
|
File diff suppressed because it is too large
Load diff
|
@ -1,937 +0,0 @@
|
|||
/// <reference path="./ModalPermissionEdit.ts" /> /* first needs the AbstractPermissionEdit */
|
||||
|
||||
import {
|
||||
GroupedPermissions,
|
||||
PermissionGroup,
|
||||
PermissionInfo,
|
||||
PermissionValue
|
||||
} from "tc-shared/permission/PermissionManager";
|
||||
import * as contextmenu from "tc-shared/ui/elements/ContextMenu";
|
||||
import {createInfoModal} from "tc-shared/ui/elements/Modal";
|
||||
import {copy_to_clipboard} from "tc-shared/utils/helpers";
|
||||
import PermissionType from "tc-shared/permission/PermissionType";
|
||||
import {LogCategory} from "tc-shared/log";
|
||||
import * as log from "tc-shared/log";
|
||||
import {
|
||||
AbstractPermissionEditor,
|
||||
ChangedPermissionValue,
|
||||
PermissionEditorMode
|
||||
} from "tc-shared/ui/modal/permission/AbstractPermissionEditor";
|
||||
import {icon_cache_loader, IconManager} from "tc-shared/file/Icons";
|
||||
|
||||
class HTMLPermission {
|
||||
readonly handle: HTMLPermissionEditor;
|
||||
readonly group: HTMLPermissionGroup;
|
||||
readonly permission: PermissionInfo;
|
||||
readonly index: number;
|
||||
|
||||
tag: JQuery;
|
||||
tag_name: JQuery;
|
||||
tag_container_value: JQuery;
|
||||
tag_container_granted: JQuery;
|
||||
tag_container_skip: JQuery;
|
||||
tag_container_negate: JQuery;
|
||||
|
||||
hidden: boolean;
|
||||
|
||||
/* the "actual" values */
|
||||
private _mask = 0; /* fourth bit: hidden by filer | third bit: value type | second bit: grant shown | first bit: value shown */
|
||||
|
||||
private _tag_value: JQuery;
|
||||
private _tag_value_input: JQuery;
|
||||
|
||||
private _tag_granted: JQuery;
|
||||
private _tag_granted_input: JQuery;
|
||||
|
||||
private _tag_skip: JQuery;
|
||||
private _tag_skip_input: JQuery;
|
||||
|
||||
private _tag_negate: JQuery;
|
||||
private _tag_negate_input: JQuery;
|
||||
|
||||
private _value: number | undefined;
|
||||
private _grant: number | undefined;
|
||||
private flags: number; /* 0x01 := Skip | 0x02 := Negate */
|
||||
|
||||
constructor(handle: HTMLPermissionEditor, group: HTMLPermissionGroup, permission: PermissionInfo, index: number) {
|
||||
this.handle = handle;
|
||||
this.permission = permission;
|
||||
this.index = index;
|
||||
this.group = group;
|
||||
|
||||
this.build_tag();
|
||||
}
|
||||
|
||||
private static build_checkbox() : {tag: JQuery, input: JQuery} {
|
||||
let tag, input;
|
||||
tag = $.spawn("label").addClass("switch").append([
|
||||
input = $.spawn("input").attr("type", "checkbox"),
|
||||
$.spawn("span").addClass("slider").append(
|
||||
$.spawn("div").addClass("dot")
|
||||
)
|
||||
]);
|
||||
return {tag: tag, input: input};
|
||||
}
|
||||
|
||||
private static number_filter_re = /^[-+]?([0-9]{0,9})$/;
|
||||
private build_tag() {
|
||||
this.tag = $.spawn("div").addClass("entry permission").css('padding-left', this.index + "em").append([
|
||||
this.tag_name = $.spawn("div").addClass("column-name").text(this.permission.name),
|
||||
this.tag_container_value = $.spawn("div").addClass("column-value"),
|
||||
this.tag_container_skip = $.spawn("div").addClass("column-skip"),
|
||||
this.tag_container_negate = $.spawn("div").addClass("column-negate"),
|
||||
this.tag_container_granted = $.spawn("div").addClass("column-granted")
|
||||
]);
|
||||
|
||||
if(this.permission.is_boolean()) {
|
||||
let value = HTMLPermission.build_checkbox();
|
||||
this._tag_value = value.tag;
|
||||
this._tag_value_input = value.input;
|
||||
|
||||
this._tag_value_input.on('change', event => {
|
||||
const value = this._tag_value_input.prop('checked') ? 1 : 0;
|
||||
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: false,
|
||||
|
||||
value: value,
|
||||
flag_skip: (this.flags & 0x01) > 0,
|
||||
flag_negate: (this.flags & 0x02) > 0
|
||||
}).then(() => {
|
||||
this._value = value;
|
||||
}).catch(error => {
|
||||
this._reset_value();
|
||||
});
|
||||
});
|
||||
|
||||
this._mask |= 0x04;
|
||||
} else {
|
||||
this._tag_value = $.spawn("input").addClass("number");
|
||||
this._tag_value_input = this._tag_value;
|
||||
this._tag_value_input.attr("type", "number");
|
||||
this._tag_value_input.on('change blur', event => {
|
||||
const str_value = this._tag_value_input.val() as string;
|
||||
const value = parseInt(str_value);
|
||||
if(!HTMLPermission.number_filter_re.test(str_value) || isNaN(value)) {
|
||||
console.warn(tr("Failed to parse given permission value string: %s"), str_value);
|
||||
this._reset_value();
|
||||
return;
|
||||
}
|
||||
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: false,
|
||||
|
||||
value: value,
|
||||
flag_skip: (this.flags & 0x01) > 0,
|
||||
flag_negate: (this.flags & 0x02) > 0
|
||||
}).then(() => {
|
||||
this._value = value;
|
||||
this._update_active_class();
|
||||
}).catch(error => {
|
||||
this._reset_value();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let skip = HTMLPermission.build_checkbox();
|
||||
this._tag_skip = skip.tag;
|
||||
this._tag_skip_input = skip.input;
|
||||
|
||||
this._tag_skip_input.on('change', event => {
|
||||
const value = this._tag_skip_input.prop('checked');
|
||||
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: false,
|
||||
|
||||
value: this._value,
|
||||
flag_skip: value,
|
||||
flag_negate: (this.flags & 0x02) > 0
|
||||
}).then(() => {
|
||||
if(value)
|
||||
this.flags |= 0x01;
|
||||
else
|
||||
this.flags &= ~0x1;
|
||||
this._update_active_class();
|
||||
}).catch(error => {
|
||||
this._reset_value();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let negate = HTMLPermission.build_checkbox();
|
||||
this._tag_negate = negate.tag;
|
||||
this._tag_negate_input = negate.input;
|
||||
|
||||
this._tag_negate_input.on('change blur', event => {
|
||||
const value = this._tag_negate_input.prop('checked');
|
||||
|
||||
console.log("Negate value: %o", value);
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: false,
|
||||
|
||||
value: this._value,
|
||||
flag_skip: (this.flags & 0x01) > 0,
|
||||
flag_negate: value
|
||||
}).then(() => {
|
||||
if(value)
|
||||
this.flags |= 0x02;
|
||||
else
|
||||
this.flags &= ~0x2;
|
||||
this._update_active_class();
|
||||
}).catch(error => {
|
||||
this._reset_value();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
this._tag_granted = $.spawn("input").addClass("number");
|
||||
this._tag_granted_input = this._tag_granted;
|
||||
|
||||
this._tag_granted_input.attr("type", "number");
|
||||
this._tag_granted_input.on('change', event => {
|
||||
const str_value = this._tag_granted_input.val() as string;
|
||||
const value = parseInt(str_value);
|
||||
if(!HTMLPermission.number_filter_re.test(str_value) || Number.isNaN(value)) {
|
||||
console.warn(tr("Failed to parse given permission granted value string: %o"), str_value);
|
||||
this._reset_value();
|
||||
return;
|
||||
}
|
||||
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: false,
|
||||
|
||||
granted: value
|
||||
}).then(() => {
|
||||
this._grant = value;
|
||||
this._update_active_class();
|
||||
}).catch(error => {
|
||||
this._reset_grant();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* double click handler */
|
||||
{
|
||||
this.tag.on('dblclick', event => this._trigger_value_assign())
|
||||
}
|
||||
|
||||
/* context menu */
|
||||
{
|
||||
this.tag.on('contextmenu', event => {
|
||||
if(event.isDefaultPrevented())
|
||||
return;
|
||||
event.preventDefault();
|
||||
|
||||
let entries: contextmenu.MenuEntry[] = [];
|
||||
if(typeof(this._value) === "undefined") {
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Add permission"),
|
||||
callback: () => this._trigger_value_assign()
|
||||
});
|
||||
} else {
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Remove permission"),
|
||||
callback: () => {
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: true,
|
||||
value: 0
|
||||
}).then(() => {
|
||||
this.value(undefined);
|
||||
}).catch(error => {
|
||||
//We have to do nothing
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(typeof(this._grant) === "undefined") {
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Add grant permission"),
|
||||
callback: () => this._trigger_grant_assign()
|
||||
});
|
||||
} else {
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Remove grant permission"),
|
||||
callback: () => {
|
||||
this.handle.trigger_change(this.permission, {
|
||||
remove: true,
|
||||
granted: 0
|
||||
}).then(() => {
|
||||
this.granted(undefined);
|
||||
}).catch(error => {
|
||||
//We have to do nothing
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
if(this.group.collapsed)
|
||||
entries.push({ /* This could never happen! */
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend group"),
|
||||
callback: () => this.group.expend()
|
||||
});
|
||||
else
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse group"),
|
||||
callback: () => this.group.collapse()
|
||||
});
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => this.handle.expend_all()
|
||||
});
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => this.handle.collapse_all()
|
||||
});
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Show permission description"),
|
||||
callback: () => {
|
||||
createInfoModal(
|
||||
tr("Permission description"),
|
||||
tr("Permission description for permission ") + this.permission.name + ": <br>" + this.permission.description
|
||||
).open();
|
||||
}
|
||||
});
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Copy permission name"),
|
||||
callback: () => {
|
||||
copy_to_clipboard(this.permission.name);
|
||||
}
|
||||
});
|
||||
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, ...entries);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _trigger_value_assign() {
|
||||
if(typeof(this._value) === "undefined")
|
||||
this.value(this._grant || 1, false, false); //TODO: Use max granted value?
|
||||
this._tag_value_input.focus();
|
||||
if(this.permission.is_boolean())
|
||||
this._tag_value_input.trigger('change');
|
||||
}
|
||||
|
||||
private _trigger_grant_assign() {
|
||||
this.granted(1); //TODO: Use max granted value?
|
||||
this._tag_granted_input.focus();
|
||||
}
|
||||
|
||||
hide() {
|
||||
this._mask &= ~0x08;
|
||||
for(const element of this.tag)
|
||||
(<HTMLElement>element).style.display = 'none';
|
||||
}
|
||||
|
||||
show() {
|
||||
this._mask |= 0x08;
|
||||
for(const element of this.tag)
|
||||
(<HTMLElement>element).style.display = 'flex';
|
||||
}
|
||||
|
||||
is_filtered() : boolean {
|
||||
return (this._mask & 0x10) > 0;
|
||||
}
|
||||
|
||||
set_filtered(flag: boolean) {
|
||||
if(flag)
|
||||
this._mask |= 0x10;
|
||||
else
|
||||
this._mask &= ~0x10;
|
||||
}
|
||||
|
||||
is_set() : boolean {
|
||||
return (this._mask & 0x03) > 0;
|
||||
}
|
||||
|
||||
get_value() { return this._value; }
|
||||
|
||||
value(value: number | undefined, skip?: boolean, negate?: boolean) {
|
||||
if(typeof value === "undefined") {
|
||||
this._tag_value.detach();
|
||||
this._tag_negate.detach();
|
||||
this._tag_skip.detach();
|
||||
|
||||
this._value = undefined;
|
||||
this.flags = 0;
|
||||
|
||||
this._update_active_class();
|
||||
this._mask &= ~0x1;
|
||||
return;
|
||||
}
|
||||
|
||||
if((this._mask & 0x1) == 0) {
|
||||
this._tag_value.appendTo(this.tag_container_value);
|
||||
this._tag_negate.appendTo(this.tag_container_negate);
|
||||
this._tag_skip.appendTo(this.tag_container_skip);
|
||||
|
||||
this._update_active_class();
|
||||
this._mask |= 0x01;
|
||||
}
|
||||
|
||||
if((this._mask & 0x04) > 0)
|
||||
this._tag_value_input.prop('checked', !!value);
|
||||
else
|
||||
this._tag_value_input.val(value);
|
||||
this._tag_skip_input.prop('checked', !!skip);
|
||||
this._tag_negate_input.prop('checked', !!negate);
|
||||
|
||||
this._value = value;
|
||||
this.flags = (!!skip ? 0x01 : 0) | (!!negate ? 0x2 : 0);
|
||||
}
|
||||
|
||||
granted(value: number | undefined) {
|
||||
if(typeof value === "undefined") {
|
||||
this._tag_granted.detach();
|
||||
|
||||
this._update_active_class();
|
||||
this._grant = undefined;
|
||||
this._mask &= ~0x2;
|
||||
return;
|
||||
}
|
||||
|
||||
if((this._mask & 0x2) == 0) {
|
||||
this._mask |= 0x02;
|
||||
this._tag_granted.appendTo(this.tag_container_granted);
|
||||
this._update_active_class();
|
||||
}
|
||||
this._tag_granted_input.val(value);
|
||||
this._grant = value;
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._mask &= ~0x03;
|
||||
|
||||
this._tag_value.detach();
|
||||
this._tag_negate.detach();
|
||||
this._tag_skip.detach();
|
||||
|
||||
this._tag_granted.detach();
|
||||
|
||||
this._value = undefined;
|
||||
this._grant = undefined;
|
||||
this.flags = 0;
|
||||
|
||||
const tag = this.tag[0] as HTMLDivElement;
|
||||
tag.classList.remove("active");
|
||||
}
|
||||
|
||||
private _reset_value() {
|
||||
if(typeof(this._value) === "undefined") {
|
||||
if((this._mask & 0x1) != 0)
|
||||
this.value(undefined);
|
||||
} else {
|
||||
this.value(this._value, (this.flags & 0x1) > 1, (this.flags & 0x2) > 1);
|
||||
}
|
||||
}
|
||||
|
||||
private _reset_grant() {
|
||||
if(typeof(this._grant) === "undefined") {
|
||||
if((this._mask & 0x2) != 0)
|
||||
this.granted(undefined);
|
||||
} else {
|
||||
this.granted(this._grant);
|
||||
}
|
||||
}
|
||||
|
||||
private _update_active_class() {
|
||||
const value = typeof(this._value) !== "undefined" || typeof(this._grant) !== "undefined";
|
||||
const tag = this.tag[0] as HTMLDivElement;
|
||||
if(value)
|
||||
tag.classList.add("active");
|
||||
else
|
||||
tag.classList.remove("active");
|
||||
}
|
||||
}
|
||||
|
||||
class HTMLPermissionGroup {
|
||||
readonly handle: HTMLPermissionEditor;
|
||||
readonly group: PermissionGroup;
|
||||
readonly index: number;
|
||||
|
||||
private _tag_arrow: JQuery;
|
||||
|
||||
permissions: HTMLPermission[] = [];
|
||||
children: HTMLPermissionGroup[] = [];
|
||||
|
||||
tag: JQuery;
|
||||
visible: boolean;
|
||||
|
||||
collapsed: boolean;
|
||||
parent_collapsed: boolean;
|
||||
|
||||
constructor(handle: HTMLPermissionEditor, group: PermissionGroup, index: number) {
|
||||
this.handle = handle;
|
||||
this.group = group;
|
||||
this.index = index;
|
||||
|
||||
this._build_tag();
|
||||
}
|
||||
|
||||
private _build_tag() {
|
||||
this.tag = $.spawn("div").addClass("entry group").css('padding-left', this.index + "em").append([
|
||||
$.spawn("div").addClass("column-name").append([
|
||||
this._tag_arrow = $.spawn("div").addClass("arrow down"),
|
||||
$.spawn("div").addClass("group-name").text(this.group.name)
|
||||
]),
|
||||
$.spawn("div").addClass("column-value"),
|
||||
$.spawn("div").addClass("column-skip"),
|
||||
$.spawn("div").addClass("column-negate"),
|
||||
$.spawn("div").addClass("column-granted")
|
||||
]);
|
||||
|
||||
this.tag.on('contextmenu', event => {
|
||||
if(event.isDefaultPrevented())
|
||||
return;
|
||||
event.preventDefault();
|
||||
|
||||
const entries: contextmenu.MenuEntry[] = [];
|
||||
if(this.collapsed)
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend group"),
|
||||
callback: () => this.expend(),
|
||||
});
|
||||
else
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse group"),
|
||||
callback: () => this.collapse(),
|
||||
});
|
||||
entries.push(contextmenu.Entry.HR());
|
||||
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => this.handle.expend_all()
|
||||
});
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => this.handle.collapse_all()
|
||||
});
|
||||
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, ...entries);
|
||||
});
|
||||
|
||||
this._tag_arrow.on('click', event => {
|
||||
if(this.collapsed)
|
||||
this.expend();
|
||||
else
|
||||
this.collapse();
|
||||
})
|
||||
}
|
||||
|
||||
update_visibility() {
|
||||
let flag = false;
|
||||
if (!flag) {
|
||||
for (const group of this.children) {
|
||||
if (group.visible) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
for (const permission of this.permissions) {
|
||||
if (!permission.is_filtered()) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.visible = flag;
|
||||
|
||||
flag = flag && !this.parent_collapsed;
|
||||
for(const element of this.tag)
|
||||
(<HTMLElement>element).style.display = flag ? 'flex' : 'none';
|
||||
|
||||
const arrow_node = this._tag_arrow[0];
|
||||
arrow_node.classList.remove(this.collapsed ? "down" : "right");
|
||||
arrow_node.classList.add(!this.collapsed ? "down" : "right");
|
||||
}
|
||||
|
||||
collapse() {
|
||||
this.collapsed = true;
|
||||
|
||||
const children = [...this.children];
|
||||
while (true) {
|
||||
const child = children.pop();
|
||||
if(!child) break;
|
||||
|
||||
child.parent_collapsed = true;
|
||||
children.push(...child.children);
|
||||
}
|
||||
|
||||
this.handle.update_view();
|
||||
}
|
||||
|
||||
expend() {
|
||||
this.collapsed = false;
|
||||
|
||||
if(this.parent_collapsed)
|
||||
return;
|
||||
|
||||
const children = [...this.children];
|
||||
while (true) {
|
||||
const child = children.pop();
|
||||
if(!child) break;
|
||||
|
||||
child.parent_collapsed = false;
|
||||
if(!child.collapsed)
|
||||
children.push(...child.children);
|
||||
}
|
||||
|
||||
this.handle.update_view();
|
||||
}
|
||||
}
|
||||
|
||||
export class HTMLPermissionEditor extends AbstractPermissionEditor {
|
||||
container: JQuery;
|
||||
|
||||
private mode_container_permissions: JQuery;
|
||||
private mode_container_error_permission: JQuery;
|
||||
private mode_container_unset: JQuery;
|
||||
|
||||
private icon_shown: boolean;
|
||||
|
||||
private filter_input: JQuery;
|
||||
private filter_grant: JQuery;
|
||||
|
||||
private hidden_permissions: PermissionType[];
|
||||
|
||||
private button_toggle: JQuery;
|
||||
|
||||
private even_list: ({ visible() : boolean; set_even(flag: boolean); })[];
|
||||
private permission_map: Array<HTMLPermission>;
|
||||
private permission_groups: HTMLPermissionGroup[];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
initialize(permissions: GroupedPermissions[]) {
|
||||
this._permissions = permissions;
|
||||
this.build_tag();
|
||||
}
|
||||
|
||||
set_hidden_permissions(permissions: PermissionType[]) {
|
||||
this.hidden_permissions = permissions;
|
||||
this.update_filter();
|
||||
}
|
||||
|
||||
private update_filter() {
|
||||
const value = (this.filter_input.val() as string).toLowerCase();
|
||||
const grant = !!this.filter_grant.prop('checked');
|
||||
|
||||
const _filter = (permission: HTMLPermission) => {
|
||||
if(value && permission.permission.name.indexOf(value) == -1) return false;
|
||||
if(grant && !permission.is_set()) return false;
|
||||
if(this.hidden_permissions && this.hidden_permissions.find(e => e && e.toLocaleLowerCase() == permission.permission.name.toLowerCase()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
for(let id = 1; id < this.permission_map.length; id++) {
|
||||
const permission = this.permission_map[id];
|
||||
let flag = _filter(permission);
|
||||
permission.set_filtered(!flag);
|
||||
|
||||
|
||||
flag = flag && !permission.group.collapsed && !permission.group.parent_collapsed; /* hide when parent is filtered */
|
||||
if(flag) permission.show();
|
||||
else permission.hide();
|
||||
}
|
||||
|
||||
/* run in both directions, to update the parent visibility and the actiual visibility */
|
||||
for(const group of this.permission_groups)
|
||||
group.update_visibility();
|
||||
for(const group of this.permission_groups.slice().reverse())
|
||||
group.update_visibility();
|
||||
|
||||
|
||||
let index = 0;
|
||||
for(const entry of this.even_list) {
|
||||
if(!entry.visible()) continue;
|
||||
entry.set_even((index++ & 0x1) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
private update_icon() {
|
||||
const permission = this.icon_shown ? this.permission_map.find(e => e && e.permission.name === "i_icon_id") : undefined;
|
||||
const icon_id = permission ? permission.get_value() : 0;
|
||||
|
||||
const icon_node = this.container.find(".container-icon-select .icon-preview");
|
||||
icon_node.children().remove();
|
||||
|
||||
let resolve: Promise<JQuery<HTMLDivElement>>;
|
||||
if(icon_id >= 0 && icon_id <= 1000)
|
||||
resolve = Promise.resolve(IconManager.generate_tag(icon_cache_loader.load_icon(icon_id, "general")));
|
||||
else
|
||||
resolve = this.icon_resolver(permission ? permission.get_value() : 0).then(e => $(e));
|
||||
|
||||
resolve.then(tag => tag.appendTo(icon_node))
|
||||
.catch(error => {
|
||||
log.error(LogCategory.PERMISSIONS, tr("Failed to generate empty icon preview: %o"), error);
|
||||
});
|
||||
}
|
||||
|
||||
private build_tag() {
|
||||
this.container = $("#tmpl_permission_editor_html").renderTag();
|
||||
this.container.find("input").on('change', event => {
|
||||
$(event.target).parents(".form-group").toggleClass('is-filled', !!(event.target as HTMLInputElement).value);
|
||||
});
|
||||
|
||||
/* search for that as long we've not that much nodes */
|
||||
this.mode_container_permissions = this.container.find(".container-mode-permissions");
|
||||
this.mode_container_error_permission = this.container.find(".container-mode-no-permissions");
|
||||
this.mode_container_unset = this.container.find(".container-mode-unset");
|
||||
|
||||
this.filter_input = this.container.find(".filter-input");
|
||||
this.filter_input.on('change keyup', event => this.update_filter());
|
||||
|
||||
this.filter_grant = this.container.find(".filter-granted");
|
||||
this.filter_grant.on('change', event => this.update_filter());
|
||||
|
||||
this.button_toggle = this.container.find(".button-toggle-clients");
|
||||
this.button_toggle.on('click', () => {
|
||||
if(this._toggle_callback)
|
||||
this.button_toggle.text(this._toggle_callback());
|
||||
});
|
||||
|
||||
this.container.find(".button-update").on('click', event => this.trigger_update());
|
||||
|
||||
/* allocate array space */
|
||||
{
|
||||
let max_index = 0;
|
||||
let tmp: GroupedPermissions[] = [];
|
||||
while(true) {
|
||||
const entry = tmp.pop();
|
||||
if(!entry) break;
|
||||
for(const permission of entry.permissions)
|
||||
if(permission.id > max_index)
|
||||
max_index = permission.id;
|
||||
tmp.push(...entry.children);
|
||||
}
|
||||
this.permission_map = new Array(max_index + 1);
|
||||
}
|
||||
this.permission_groups = [];
|
||||
this.even_list = [];
|
||||
|
||||
{
|
||||
const container_permission = this.mode_container_permissions.find(".container-permission-list .body");
|
||||
|
||||
const build_group = (pgroup: HTMLPermissionGroup, group: GroupedPermissions, index: number) => {
|
||||
const hgroup = new HTMLPermissionGroup(this, group.group, index);
|
||||
hgroup.tag.appendTo(container_permission);
|
||||
this.even_list.push({
|
||||
set_even(flag: boolean) {
|
||||
if(flag)
|
||||
hgroup.tag[0].classList.add('even');
|
||||
else
|
||||
hgroup.tag[0].classList.remove('even');
|
||||
},
|
||||
|
||||
visible(): boolean {
|
||||
return !hgroup.parent_collapsed && hgroup.visible;
|
||||
}
|
||||
});
|
||||
|
||||
if(pgroup)
|
||||
pgroup.children.push(hgroup);
|
||||
this.permission_groups.push(hgroup);
|
||||
|
||||
index++;
|
||||
for(const child of group.children)
|
||||
build_group(hgroup, child, index);
|
||||
|
||||
for(const permission of group.permissions) {
|
||||
const perm = new HTMLPermission(this, hgroup, permission, index);
|
||||
this.permission_map[perm.permission.id] = perm;
|
||||
perm.tag.appendTo(container_permission);
|
||||
hgroup.permissions.push(perm);
|
||||
this.even_list.push({
|
||||
set_even(flag: boolean) {
|
||||
if(flag)
|
||||
perm.tag[0].classList.add('even');
|
||||
else
|
||||
perm.tag[0].classList.remove('even');
|
||||
},
|
||||
|
||||
visible(): boolean {
|
||||
return !perm.is_filtered() && !perm.group.collapsed && !perm.group.parent_collapsed;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for(const group of this._permissions)
|
||||
build_group(undefined, group, 0);
|
||||
}
|
||||
|
||||
{
|
||||
const container = this.container.find(".container-icon-select");
|
||||
container.find(".button-select-icon").on('click', event => {
|
||||
const permission = this.permission_map.find(e => e && e.permission.name === "i_icon_id");
|
||||
this.icon_selector(permission ? permission.get_value() : 0).then(id => {
|
||||
const permission = this.permission_map.find(e => e && e.permission.name === "i_icon_id");
|
||||
if(permission) {
|
||||
this.trigger_change(permission.permission, {
|
||||
remove: false,
|
||||
value: id,
|
||||
flag_skip: false,
|
||||
flag_negate: false
|
||||
}, false).then(() => {
|
||||
log.debug(LogCategory.PERMISSIONS, tr("Selected new icon %s"), id);
|
||||
|
||||
permission.value(id, false, false);
|
||||
this.update_icon();
|
||||
}).catch(error => {
|
||||
log.warn(LogCategory.PERMISSIONS, tr("Failed to set icon permission within permission editor: %o"), error);
|
||||
});
|
||||
} else {
|
||||
log.warn(LogCategory.PERMISSIONS, tr("Failed to find icon permissions within permission editor"));
|
||||
}
|
||||
}).catch(error => {
|
||||
log.error(LogCategory.PERMISSIONS, tr("Failed to select an icon for the icon permission: %o"), error);
|
||||
});
|
||||
});
|
||||
|
||||
container.find(".button-icon-remove").on('click', event => {
|
||||
const permission = this.permission_map.find(e => e && e.permission.name === "i_icon_id");
|
||||
if(permission) {
|
||||
this.trigger_change(permission.permission, {
|
||||
remove: true,
|
||||
}, false).then(() => {
|
||||
permission.value(undefined);
|
||||
this.update_icon();
|
||||
}).catch(error => {
|
||||
log.warn(LogCategory.PERMISSIONS, tr("Failed to remove icon permission within permission editor: %o"), error);
|
||||
});
|
||||
} else {
|
||||
log.warn(LogCategory.PERMISSIONS, tr("Failed to find icon permission within permission editor"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.mode_container_permissions.on('contextmenu', event => {
|
||||
if(event.isDefaultPrevented())
|
||||
return;
|
||||
event.preventDefault();
|
||||
|
||||
const entries: contextmenu.MenuEntry[] = [];
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Expend all"),
|
||||
callback: () => this.expend_all()
|
||||
});
|
||||
entries.push({
|
||||
type: contextmenu.MenuEntryType.ENTRY,
|
||||
name: tr("Collapse all"),
|
||||
callback: () => this.collapse_all()
|
||||
});
|
||||
|
||||
contextmenu.spawn_context_menu(event.pageX, event.pageY, ...entries);
|
||||
});
|
||||
|
||||
this.set_mode(PermissionEditorMode.UNSET);
|
||||
}
|
||||
|
||||
html_tag(): JQuery<HTMLElement> {
|
||||
return this.container;
|
||||
}
|
||||
|
||||
set_permissions(u_permissions?: PermissionValue[]) {
|
||||
const permissions = new Array<PermissionValue>(this.permission_map.length);
|
||||
|
||||
/* initialize update array, boundary checks are already made by js */
|
||||
for(const perm of u_permissions)
|
||||
permissions[perm.type.id] = perm;
|
||||
|
||||
/* there is no permission with id 0 */
|
||||
for(let id = 1; id < permissions.length; id++) {
|
||||
const new_permission = permissions[id];
|
||||
const permission_handle = this.permission_map[id];
|
||||
if(!new_permission) {
|
||||
permission_handle.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
permission_handle.value(new_permission.value, new_permission.flag_skip, new_permission.flag_negate);
|
||||
permission_handle.granted(new_permission.granted_value);
|
||||
}
|
||||
|
||||
this.update_icon();
|
||||
this.update_filter();
|
||||
}
|
||||
|
||||
set_mode(mode: PermissionEditorMode) {
|
||||
this.mode_container_permissions.css('display', mode == PermissionEditorMode.VISIBLE ? 'flex' : 'none');
|
||||
this.mode_container_error_permission.css('display', mode == PermissionEditorMode.NO_PERMISSION ? 'flex' : 'none');
|
||||
this.mode_container_unset.css('display', mode == PermissionEditorMode.UNSET ? 'block' : 'none');
|
||||
if(this.icon_shown != (mode == PermissionEditorMode.VISIBLE)) {
|
||||
this.icon_shown = mode == PermissionEditorMode.VISIBLE;
|
||||
this.update_icon();
|
||||
}
|
||||
}
|
||||
|
||||
trigger_change(permission: PermissionInfo, value?: ChangedPermissionValue, update_icon?: boolean) : Promise<void> {
|
||||
if(this._listener_change) {
|
||||
if((typeof(update_icon) !== "boolean" || update_icon) && permission && permission.name === "i_icon_id")
|
||||
return this._listener_change(permission, value).then(e => {
|
||||
setTimeout(() => this.update_icon(), 0); /* we need to fully handle the response and then only we're able to update the icon */
|
||||
return e;
|
||||
});
|
||||
else
|
||||
return this._listener_change(permission, value);
|
||||
}
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
collapse_all() {
|
||||
for(const group of this.permission_groups) {
|
||||
group.collapsed = true;
|
||||
for(const child of group.children)
|
||||
child.parent_collapsed = true;
|
||||
}
|
||||
this.update_filter(); /* update display state of all entries */
|
||||
}
|
||||
|
||||
expend_all() {
|
||||
for(const group of this.permission_groups) {
|
||||
group.collapsed = false;
|
||||
group.parent_collapsed = false;
|
||||
}
|
||||
this.update_filter(); /* update display state of all entries */
|
||||
}
|
||||
|
||||
update_view() { return this.update_filter(); }
|
||||
|
||||
set_toggle_button(callback: () => string, initial: string) {
|
||||
this._toggle_callback = callback;
|
||||
if(this._toggle_callback) {
|
||||
this.button_toggle.text(initial);
|
||||
this.button_toggle.show();
|
||||
} else {
|
||||
this.button_toggle.hide();
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -10,8 +10,8 @@ import {
|
|||
EditorGroupedPermissions,
|
||||
PermissionEditor,
|
||||
PermissionEditorEvents
|
||||
} from "tc-shared/ui/modal/permissionv2/PermissionEditor";
|
||||
import {SideBar} from "tc-shared/ui/modal/permissionv2/TabHandler";
|
||||
} from "tc-shared/ui/modal/permission/PermissionEditor";
|
||||
import {SideBar} from "tc-shared/ui/modal/permission/TabHandler";
|
||||
import {Group, GroupTarget, GroupType} from "tc-shared/permission/GroupManager";
|
||||
import {createErrorModal, createInfoModal} from "tc-shared/ui/elements/Modal";
|
||||
import {ClientNameInfo, CommandResult, ErrorID} from "tc-shared/connection/ServerConnectionDeclaration";
|
|
@ -4,8 +4,6 @@ export const senseless_server_group_permissions: PermissionType[] = [
|
|||
PermissionType.B_CHANNEL_GROUP_INHERITANCE_END
|
||||
];
|
||||
|
||||
/* TODO: All the needed permissions! */
|
||||
|
||||
const filter = (text, ignore_type) => Object.keys(PermissionType)
|
||||
.filter(e => e.toLowerCase().substr(ignore_type ? 1 : 0).startsWith(text)).map(e => PermissionType[e]);
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
ChannelInfo,
|
||||
GroupProperties,
|
||||
PermissionModalEvents
|
||||
} from "tc-shared/ui/modal/permissionv2/ModalPermissionEditor";
|
||||
import {PermissionEditorEvents} from "tc-shared/ui/modal/permissionv2/PermissionEditor";
|
||||
} from "tc-shared/ui/modal/permission/ModalPermissionEditor";
|
||||
import {PermissionEditorEvents} from "tc-shared/ui/modal/permission/PermissionEditor";
|
||||
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
|
||||
import {LocalIconRenderer} from "tc-shared/ui/react-elements/Icon";
|
||||
import {createInputModal} from "tc-shared/ui/elements/Modal";
|
Loading…
Add table
Reference in a new issue