mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-30 14:09:33 +02:00
fix admin
This commit is contained in:
6 files changed
+380
-65
No files matched your search
Vendored
+1
-1
@@ -6,4 +6,4 @@
|
||||
*/:root{--blue:#007bff;--indigo:#6610f2;--purple:#6f42c1;--pink:#e83e8c;--red:#dc3545;--orange:#fd7e14;--yellow:#ffc107;--green:#28a745;--teal:#20c997;--cyan:#17a2b8;--white:#fff;--gray:#6c757d;--gray-dark:#343a40;--primary:#007bff;--secondary:#6c757d;--success:#28a745;--info:#17a2b8;--warning:#ffc107;--danger:#dc3545;--light:#f8f9fa;--dark:#343a40;--breakpoint-xs:0;--breakpoint-sm:576px;--breakpoint-md:768px;--breakpoint-lg:992px;--breakpoint-xl:1200px;--font-family-sans-serif:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace}*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]){color:inherit;text-decoration:none}a:not([href]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{margin-bottom:.5rem;font-weight:500;line-height:1.2}.h1,h1{font-size:2.5rem}.h2,h2{font-size:2rem}.h3,h3{font-size:1.75rem}.h4,h4{font-size:1.5rem}.h5,h5{font-size:1.25rem}.h6,h6{font-size:1rem}.lead{font-size:1.25rem;font-weight:300}.display-1{font-size:6rem;font-weight:300;line-height:1.2}.display-2{font-size:5.5rem;font-weight:300;line-height:1.2}.display-3{font-size:4.5rem;font-weight:300;line-height:1.2}.display-4{font-size:3.5rem;font-weight:300;line-height:1.2}hr{margin-top:1rem;margin-bottom:1rem;border:0;border-top:1px solid rgba(0,0,0,.1)}.small,small{font-size:80%;font-weight:400}.mark,mark{padding:.2em;background-color:#fcf8e3}.list-unsLine truncated
|
||||
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
*/.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{contentLine truncated
|
||||
*/.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{contentLine truncated
|
||||
+196
-26
@@ -1037,21 +1037,53 @@ a:hover {
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
background-color: var(--main-bg-color);
|
||||
padding: 8px 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background-color: var(--canvas-bg-color);
|
||||
padding: 10px 14px;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
border-radius: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.status-bar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.status-bar-actions .btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: var(--paper-card);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--color);
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
font-size: 12.5px;
|
||||
min-height: 30px;
|
||||
}
|
||||
.status-bar-actions .btn:hover {
|
||||
background: var(--hover-bg-color);
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
.paths {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: initial;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
align-items: center;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.paths::-webkit-scrollbar { display: none; }
|
||||
|
||||
.paths a {
|
||||
color: var(--color);
|
||||
@@ -1988,22 +2020,27 @@ code {
|
||||
font-size: 16px; /* Prevents iOS zoom */
|
||||
}
|
||||
|
||||
/* File explorer mobile layout */
|
||||
.leftCol {
|
||||
max-height: 40vh;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* Status bar wrapping */
|
||||
.status-bar {
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
gap: 6px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
|
||||
.status-bar .btn {
|
||||
font-size: 12px;
|
||||
padding: 3px 8px;
|
||||
min-height: 28px;
|
||||
padding: 4px 10px;
|
||||
min-height: 32px;
|
||||
}
|
||||
.status-bar .paths {
|
||||
font-size: 11.5px;
|
||||
overflow-x: auto;
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.status-bar .paths::-webkit-scrollbar { display: none; }
|
||||
.status-bar-actions {
|
||||
flex-shrink: 0;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* Home hero section */
|
||||
@@ -2155,27 +2192,160 @@ code {
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile toggle for file explorer sidebar */
|
||||
/* ===== Explorer page (paper) ===== */
|
||||
.explorer-page {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--canvas-bg-color);
|
||||
position: relative;
|
||||
}
|
||||
.explorer-main {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--canvas-bg-color);
|
||||
}
|
||||
.explorer-content {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.leftCol-head,
|
||||
.leftCol-foot,
|
||||
.leftCol-close {
|
||||
display: none;
|
||||
}
|
||||
.leftCol-body {
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
.leftCol-foot {
|
||||
padding: 8px 12px;
|
||||
border-top: 1px solid var(--border-color);
|
||||
background: var(--paper-bg-alt);
|
||||
}
|
||||
.leftCol-foot .last-update {
|
||||
border-top: none;
|
||||
padding: 0;
|
||||
}
|
||||
.leftCol-backdrop { display: none; }
|
||||
|
||||
.paper-inline-warning {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin: 8px;
|
||||
padding: 10px 12px;
|
||||
background: rgba(138, 107, 30, 0.08);
|
||||
border: 1px solid rgba(138, 107, 30, 0.35);
|
||||
border-radius: 8px;
|
||||
color: var(--color);
|
||||
font-size: 12.5px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.paper-inline-warning i { color: #8A6B1E; margin-top: 2px; flex-shrink: 0; }
|
||||
.dark-mode .paper-inline-warning i { color: #FFD37A; }
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.leftCol-body { padding: 8px 4px; }
|
||||
}
|
||||
|
||||
/* Mobile / tablet toggle */
|
||||
.sidebar-toggle {
|
||||
display: none;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
background: var(--sidebar-bg-color);
|
||||
border: 1px solid var(--border-color);
|
||||
color: var(--color);
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
position: fixed;
|
||||
bottom: 18px;
|
||||
left: 18px;
|
||||
z-index: 1100;
|
||||
padding: 10px 14px;
|
||||
background: var(--color);
|
||||
color: var(--canvas-bg-color);
|
||||
border: 1px solid var(--color);
|
||||
border-radius: 999px;
|
||||
font-family: var(--font-sans);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,0.15);
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
}
|
||||
.sidebar-toggle:hover { background: var(--primary-hover-bg); }
|
||||
.sidebar-toggle:focus,
|
||||
.sidebar-toggle:focus-visible { outline: none; box-shadow: 0 6px 20px rgba(0,0,0,0.15); }
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.sidebar-toggle {
|
||||
display: block;
|
||||
@media (max-width: 991px) {
|
||||
.sidebar-toggle { display: inline-flex; }
|
||||
|
||||
/* Sidebar becomes a slide-in drawer */
|
||||
.leftCol {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: min(86vw, 340px);
|
||||
max-width: 340px;
|
||||
z-index: 1200;
|
||||
border: none;
|
||||
border-right: 1px solid var(--border-color);
|
||||
transform: translateX(0);
|
||||
transition: transform 0.22s ease;
|
||||
box-shadow: 4px 0 24px rgba(0,0,0,0.18);
|
||||
background: var(--sidebar-bg-color);
|
||||
}
|
||||
|
||||
.leftCol.collapsed {
|
||||
display: none !important;
|
||||
transform: translateX(-105%);
|
||||
box-shadow: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leftCol-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 14px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
background: var(--paper-bg-alt);
|
||||
}
|
||||
.leftCol-eyebrow {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.14em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
.leftCol-close {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
color: var(--ink-muted);
|
||||
cursor: pointer;
|
||||
}
|
||||
.leftCol-close:hover { color: var(--color); border-color: var(--color); }
|
||||
.leftCol-foot { display: block; }
|
||||
.leftCol-body { padding: 4px 0; }
|
||||
|
||||
.leftCol-backdrop {
|
||||
display: block;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.32);
|
||||
z-index: 1150;
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
.dark-mode .leftCol-backdrop { background: rgba(0,0,0,0.5); }
|
||||
}
|
||||
|
||||
/* ===== Admin Interface (Paper style) ===== */
|
||||
|
||||
@@ -1,64 +1,77 @@
|
||||
<div class="container-fluid h-100">
|
||||
<div class="row h-100">
|
||||
<div class="explorer-page" ng-init="sidebarCollapsed = window.matchMedia && window.matchMedia('(max-width: 767px)').matches">
|
||||
<button
|
||||
class="sidebar-toggle"
|
||||
ng-show="files.length"
|
||||
ng-click="sidebarCollapsed = !sidebarCollapsed"
|
||||
aria-label="{{sidebarCollapsed ? 'Show files' : 'Hide files'}}"
|
||||
>
|
||||
<i class="fas" ng-class="sidebarCollapsed ? 'fa-folder-open' : 'fa-times'"></i>
|
||||
{{sidebarCollapsed ? 'Show Files' : 'Hide Files'}}
|
||||
<span ng-bind="sidebarCollapsed ? 'Files' : 'Close'"></span>
|
||||
</button>
|
||||
<div
|
||||
class="leftCol shadow p-1 overflow-auto"
|
||||
ng-show="files.length"
|
||||
ng-class="{'collapsed': sidebarCollapsed}"
|
||||
>
|
||||
|
||||
<div class="leftCol" ng-show="files.length" ng-class="{'collapsed': sidebarCollapsed}">
|
||||
<div class="leftCol-head">
|
||||
<span class="leftCol-eyebrow">Files</span>
|
||||
<button class="leftCol-close" ng-click="sidebarCollapsed = true" aria-label="Close files">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="leftCol-body">
|
||||
<div
|
||||
ng-if="options.truncatedFolders.length > 0"
|
||||
class="alert alert-warning small p-2 mb-2"
|
||||
class="paper-inline-warning"
|
||||
role="alert"
|
||||
>
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
{{ 'WARNINGS.repo_truncated' | translate }}
|
||||
</div>
|
||||
<tree class="files" file="files"></tree>
|
||||
<div class="bottom column">
|
||||
<div
|
||||
</div>
|
||||
<div class="leftCol-foot">
|
||||
<span
|
||||
class="last-update"
|
||||
data-toggle="tooltip"
|
||||
data-placement="top"
|
||||
title="{{options.lastUpdateDate}}"
|
||||
>
|
||||
Last Update: {{options.lastUpdateDate|date}}
|
||||
Updated {{options.lastUpdateDate|date}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md h-100 overflow-auto p-0 d-flex flex-column">
|
||||
<div class="d-flex align-content-between status-bar shadow">
|
||||
<ol class="flex-grow-1 breadcrumb paths">
|
||||
<li class="breadcrumb-item" ng-repeat="p in paths" ng-bind="p">
|
||||
Loading...
|
||||
</li>
|
||||
|
||||
<div
|
||||
class="leftCol-backdrop"
|
||||
ng-show="files.length && !sidebarCollapsed"
|
||||
ng-click="sidebarCollapsed = true"
|
||||
></div>
|
||||
|
||||
<div class="explorer-main">
|
||||
<div class="status-bar">
|
||||
<ol class="breadcrumb paths" aria-label="Path">
|
||||
<li class="breadcrumb-item" ng-repeat="p in paths" ng-bind="p"></li>
|
||||
</ol>
|
||||
<div class="d-flex flex-wrap" style="gap: 4px">
|
||||
<div class="status-bar-actions">
|
||||
<a
|
||||
ng-if="options.isAdmin || options.isOwner"
|
||||
ng-href="/anonymize/{{repoId}}"
|
||||
class="btn btn-sm"
|
||||
>Edit</a
|
||||
aria-label="Edit"
|
||||
><i class="far fa-edit"></i><span class="d-none d-md-inline"> Edit</span></a
|
||||
>
|
||||
<a
|
||||
ng-show="content != null"
|
||||
ng-href="{{url}}"
|
||||
target="__self"
|
||||
class="btn btn-sm"
|
||||
>Raw</a
|
||||
aria-label="Raw"
|
||||
><i class="fas fa-file-alt"></i><span class="d-none d-md-inline"> Raw</span></a
|
||||
>
|
||||
<a
|
||||
ng-show="content != null"
|
||||
ng-href="{{url}}&download=true"
|
||||
target="__self"
|
||||
class="btn btn-sm"
|
||||
aria-label="Download"
|
||||
><i class="fas fa-download"></i><span class="d-none d-md-inline"> Download</span></a
|
||||
>
|
||||
<a
|
||||
@@ -66,6 +79,7 @@
|
||||
ng-href="/api/repo/{{repoId}}/zip"
|
||||
target="__self"
|
||||
class="btn btn-sm"
|
||||
aria-label="Download ZIP"
|
||||
><i class="fas fa-file-archive"></i><span class="d-none d-md-inline"> ZIP</span></a
|
||||
>
|
||||
<a
|
||||
@@ -73,13 +87,13 @@
|
||||
ng-href="/w/{{repoId}}/"
|
||||
target="__self"
|
||||
class="btn btn-sm"
|
||||
>Website</a
|
||||
aria-label="Website"
|
||||
><i class="fas fa-globe"></i><span class="d-none d-md-inline"> Website</span></a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="align-items-stretch h-100 w-100 overflow-auto">
|
||||
<div class="explorer-content">
|
||||
<ng-include src="'./partials/pageView.htm'"></ng-include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
+58
-6
@@ -18,7 +18,8 @@ angular
|
||||
$scope.repositories = [];
|
||||
$scope.total = -1;
|
||||
$scope.totalPage = 0;
|
||||
$scope.query = {
|
||||
const reposAdminPrefsKey = "admin.repos.filterPrefs";
|
||||
const reposAdminDefaults = {
|
||||
page: 1,
|
||||
limit: 25,
|
||||
sort: "lastView",
|
||||
@@ -29,6 +30,11 @@ angular
|
||||
error: true,
|
||||
preparing: true,
|
||||
};
|
||||
const savedReposAdminPrefs = loadFilterPrefs(reposAdminPrefsKey) || {};
|
||||
$scope.query = Object.assign({}, reposAdminDefaults, savedReposAdminPrefs, {
|
||||
page: 1,
|
||||
search: "",
|
||||
});
|
||||
|
||||
$scope.removeCache = (repo) => {
|
||||
$http.delete("/api/admin/repos/" + repo.repoId).then(
|
||||
@@ -85,6 +91,8 @@ angular
|
||||
() => {
|
||||
clearTimeout(timeClear);
|
||||
timeClear = setTimeout(getRepositories, 500);
|
||||
const { page, search, ...persisted } = $scope.query;
|
||||
saveFilterPrefs(reposAdminPrefsKey, persisted);
|
||||
},
|
||||
true
|
||||
);
|
||||
@@ -108,12 +116,18 @@ angular
|
||||
$scope.users = [];
|
||||
$scope.total = -1;
|
||||
$scope.totalPage = 0;
|
||||
$scope.query = {
|
||||
const usersAdminPrefsKey = "admin.users.filterPrefs";
|
||||
const usersAdminDefaults = {
|
||||
page: 1,
|
||||
limit: 25,
|
||||
sort: "username",
|
||||
search: "",
|
||||
};
|
||||
const savedUsersAdminPrefs = loadFilterPrefs(usersAdminPrefsKey) || {};
|
||||
$scope.query = Object.assign({}, usersAdminDefaults, savedUsersAdminPrefs, {
|
||||
page: 1,
|
||||
search: "",
|
||||
});
|
||||
|
||||
function getUsers() {
|
||||
$http.get("/api/admin/users", { params: $scope.query }).then(
|
||||
@@ -136,6 +150,8 @@ angular
|
||||
() => {
|
||||
clearTimeout(timeClear);
|
||||
timeClear = setTimeout(getUsers, 500);
|
||||
const { page, search, ...persisted } = $scope.query;
|
||||
saveFilterPrefs(usersAdminPrefsKey, persisted);
|
||||
},
|
||||
true
|
||||
);
|
||||
@@ -159,10 +175,38 @@ angular
|
||||
$scope.userInfo;
|
||||
$scope.repositories = [];
|
||||
$scope.search = "";
|
||||
$scope.filters = {
|
||||
status: { ready: true, expired: false, removed: false },
|
||||
|
||||
const adminUserPrefsKey = "admin.user.filterPrefs";
|
||||
const adminUserDefaults = {
|
||||
filters: { status: { ready: true, expired: false, removed: false } },
|
||||
orderBy: "-anonymizeDate",
|
||||
};
|
||||
$scope.orderBy = "-anonymizeDate";
|
||||
const savedAdminUserPrefs = loadFilterPrefs(adminUserPrefsKey) || {};
|
||||
$scope.filters = {
|
||||
status: Object.assign(
|
||||
{},
|
||||
adminUserDefaults.filters.status,
|
||||
(savedAdminUserPrefs.filters && savedAdminUserPrefs.filters.status) || {}
|
||||
),
|
||||
};
|
||||
$scope.orderBy = savedAdminUserPrefs.orderBy || adminUserDefaults.orderBy;
|
||||
|
||||
$scope.$watch("orderBy", () => {
|
||||
saveFilterPrefs(adminUserPrefsKey, {
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
});
|
||||
$scope.$watch(
|
||||
"filters",
|
||||
() => {
|
||||
saveFilterPrefs(adminUserPrefsKey, {
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$scope.repoFiler = (repo) => {
|
||||
if ($scope.filters.status[repo.status] == false) return false;
|
||||
@@ -311,12 +355,18 @@ angular
|
||||
$scope.conferences = [];
|
||||
$scope.total = -1;
|
||||
$scope.totalPage = 0;
|
||||
$scope.query = {
|
||||
const confAdminPrefsKey = "admin.conferences.filterPrefs";
|
||||
const confAdminDefaults = {
|
||||
page: 1,
|
||||
limit: 25,
|
||||
sort: "name",
|
||||
search: "",
|
||||
};
|
||||
const savedConfAdminPrefs = loadFilterPrefs(confAdminPrefsKey) || {};
|
||||
$scope.query = Object.assign({}, confAdminDefaults, savedConfAdminPrefs, {
|
||||
page: 1,
|
||||
search: "",
|
||||
});
|
||||
|
||||
function getConferences() {
|
||||
$http.get("/api/admin/conferences", { params: $scope.query }).then(
|
||||
@@ -339,6 +389,8 @@ angular
|
||||
() => {
|
||||
clearTimeout(timeClear);
|
||||
timeClear = setTimeout(getConferences, 500);
|
||||
const { page, search, ...persisted } = $scope.query;
|
||||
saveFilterPrefs(confAdminPrefsKey, persisted);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
+69
-7
@@ -861,11 +861,45 @@ angular
|
||||
|
||||
$scope.items = [];
|
||||
$scope.search = "";
|
||||
$scope.typeFilter = "all";
|
||||
$scope.filters = {
|
||||
status: { ready: true, expired: true, removed: false },
|
||||
|
||||
const dashboardPrefsKey = "dashboard.filterPrefs";
|
||||
const dashboardPrefDefaults = {
|
||||
typeFilter: "all",
|
||||
filters: { status: { ready: true, expired: true, removed: false } },
|
||||
orderBy: "-anonymizeDate",
|
||||
};
|
||||
$scope.orderBy = "-anonymizeDate";
|
||||
const savedDashboardPrefs = loadFilterPrefs(dashboardPrefsKey) || {};
|
||||
$scope.typeFilter = savedDashboardPrefs.typeFilter || dashboardPrefDefaults.typeFilter;
|
||||
$scope.filters = {
|
||||
status: Object.assign(
|
||||
{},
|
||||
dashboardPrefDefaults.filters.status,
|
||||
(savedDashboardPrefs.filters && savedDashboardPrefs.filters.status) || {}
|
||||
),
|
||||
};
|
||||
$scope.orderBy = savedDashboardPrefs.orderBy || dashboardPrefDefaults.orderBy;
|
||||
|
||||
$scope.$watchGroup(
|
||||
["typeFilter", "orderBy"],
|
||||
() => {
|
||||
saveFilterPrefs(dashboardPrefsKey, {
|
||||
typeFilter: $scope.typeFilter,
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
}
|
||||
);
|
||||
$scope.$watch(
|
||||
"filters",
|
||||
() => {
|
||||
saveFilterPrefs(dashboardPrefsKey, {
|
||||
typeFilter: $scope.typeFilter,
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
function getQuota() {
|
||||
$http.get("/api/user/quota").then((res) => {
|
||||
@@ -2030,10 +2064,38 @@ angular
|
||||
|
||||
$scope.conferences = [];
|
||||
$scope.search = "";
|
||||
$scope.filters = {
|
||||
status: { ready: true, expired: false, removed: false },
|
||||
|
||||
const conferencesPrefsKey = "conferences.filterPrefs";
|
||||
const conferencesPrefDefaults = {
|
||||
filters: { status: { ready: true, expired: false, removed: false } },
|
||||
orderBy: "name",
|
||||
};
|
||||
$scope.orderBy = "name";
|
||||
const savedConferencesPrefs = loadFilterPrefs(conferencesPrefsKey) || {};
|
||||
$scope.filters = {
|
||||
status: Object.assign(
|
||||
{},
|
||||
conferencesPrefDefaults.filters.status,
|
||||
(savedConferencesPrefs.filters && savedConferencesPrefs.filters.status) || {}
|
||||
),
|
||||
};
|
||||
$scope.orderBy = savedConferencesPrefs.orderBy || conferencesPrefDefaults.orderBy;
|
||||
|
||||
$scope.$watch("orderBy", () => {
|
||||
saveFilterPrefs(conferencesPrefsKey, {
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
});
|
||||
$scope.$watch(
|
||||
"filters",
|
||||
() => {
|
||||
saveFilterPrefs(conferencesPrefsKey, {
|
||||
filters: $scope.filters,
|
||||
orderBy: $scope.orderBy,
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
$scope.removeConference = function (conf) {
|
||||
if (
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
function loadFilterPrefs(key) {
|
||||
try {
|
||||
const raw = localStorage.getItem(key);
|
||||
return raw ? JSON.parse(raw) : null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function saveFilterPrefs(key, value) {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} catch (e) {
|
||||
/* localStorage unavailable or quota exceeded */
|
||||
}
|
||||
}
|
||||
|
||||
function humanFileSize(bytes, si = false, dp = 1) {
|
||||
const thresh = si ? 1000 : 1024;
|
||||
|
||||
|
||||
Reference in new issue
Block a user