1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-23 01:20:11 +00:00

add more info to getUsers, move admin.html css to scss files

more deatils included in getUsers response in prep for feature request #5. bs4 and bs5 css are now compiled instead of being copied.
This commit is contained in:
Harvey Tindall 2020-09-16 21:42:22 +01:00
parent 7d84fdec96
commit a8b4842895
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
12 changed files with 174 additions and 126 deletions

29
api.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/json"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -458,13 +459,29 @@ func (app *appContext) DeleteInvite(gc *gin.Context) {
respond(401, "Code doesn't exist", gc) respond(401, "Code doesn't exist", gc)
} }
type userResp struct { type dateToParse struct {
UserList []respUser `json:"users"` Parsed time.Time `json:"parseme"`
}
// json magically parses datetimes so why not
func parseDt(date string) time.Time {
timeJSON := []byte("{ \"parseme\": \"" + date + "\" }")
var parsed dateToParse
json.Unmarshal(timeJSON, &parsed)
return parsed.Parsed
} }
type respUser struct { type respUser struct {
ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`
// this magically parses a string to time.time
LastActive string `json:"last_active"`
Admin bool `json:"admin"`
}
type userResp struct {
UserList []respUser `json:"users"`
} }
func (app *appContext) GetUsers(gc *gin.Context) { func (app *appContext) GetUsers(gc *gin.Context) {
@ -480,10 +497,18 @@ func (app *appContext) GetUsers(gc *gin.Context) {
} }
for _, jfUser := range users { for _, jfUser := range users {
var user respUser var user respUser
user.LastActive = "n/a"
if jfUser["LastActivityDate"] != nil {
date := parseDt(jfUser["LastActivityDate"].(string))
user.LastActive = app.formatDatetime(date)
}
user.ID = jfUser["Id"].(string)
user.Name = jfUser["Name"].(string) user.Name = jfUser["Name"].(string)
user.Admin = jfUser["Policy"].(map[string]interface{})["IsAdministrator"].(bool)
if email, ok := app.storage.emails[jfUser["Id"].(string)]; ok { if email, ok := app.storage.emails[jfUser["Id"].(string)]; ok {
user.Email = email.(string) user.Email = email.(string)
} }
resp.UserList = append(resp.UserList, user) resp.UserList = append(resp.UserList, user)
} }
gc.JSON(200, resp) gc.JSON(200, resp)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -65,82 +65,6 @@
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
{{ end }} {{ end }}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.pageContainer {
margin: 5% 20% 5% 20%;
}
@media (max-width: 1100px) {
.pageContainer {
margin: 2%;
}
}
h1 {
/*margin: 20%;*/
margin-bottom: 5%;
}
.linkGroup {
/*margin: 20%;*/
margin-bottom: 5%;
margin-top: 5%;
}
.linkForm {
/*margin: 20%;*/
margin-top: 5%;
margin-bottom: 5%;
}
.contactBox {
/*margin: 20%;*/
margin-top: 5%;
color: grey;
}
.circle {
/*margin-left: 1rem;
width: 1rem;
height: 1rem;
border-radius: 50%;
z-index: 5000;*/
-webkit-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-moz-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-o-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190); /* easeInCubic */
}
.smooth-transition {
-webkit-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-moz-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-o-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190); /* easeincubic */
}
.rotated {
transform: rotate(180deg);
-webkit-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
}
.not-rotated {
transform: rotate(0deg);
-webkit-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
}
.invite-link {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: auto;
}
.settingIcon {
margin-left: 0.2rem;
}
body.modal-open {
overflow: hidden;
}
</style>
<title>Admin</title> <title>Admin</title>
</head> </head>
<body class="smooth-transition"> <body class="smooth-transition">
@ -316,9 +240,7 @@
</div> </div>
</div> </div>
<div class="pageContainer"> <div class="pageContainer">
<h1> <h1><a class="text-button">Invites </a></h1>
Accounts admin
</h1>
<div class="btn-group" role="group" id="headerButtons"> <div class="btn-group" role="group" id="headerButtons">
<button type="button" class="btn btn-primary" id="openSettings"> <button type="button" class="btn btn-primary" id="openSettings">
Settings <i class="fa fa-cog"></i> Settings <i class="fa fa-cog"></i>

96
scss/base.scss Normal file
View File

@ -0,0 +1,96 @@
.pageContainer {
margin: 5% 20% 5% 20%;
}
@media (max-width: 1100px) {
.pageContainer {
margin: 2%;
}
}
h1 {
/*margin: 20%;*/
margin-bottom: 5%;
}
.linkGroup {
/*margin: 20%;*/
margin-bottom: 5%;
margin-top: 5%;
}
.linkForm {
/*margin: 20%;*/
margin-top: 5%;
margin-bottom: 5%;
}
.contactBox {
/*margin: 20%;*/
margin-top: 5%;
color: grey;
}
.circle {
/*margin-left: 1rem;
width: 1rem;
height: 1rem;
border-radius: 50%;
z-index: 5000;*/
-webkit-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-moz-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-o-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190); /* easeInCubic */
}
.smooth-transition {
-webkit-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-moz-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
-o-transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190);
transition: all 300ms cubic-bezier(0.550, 0.055, 0.675, 0.190); /* easeincubic */
}
.rotated {
transform: rotate(180deg);
-webkit-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
}
.not-rotated {
transform: rotate(0deg);
-webkit-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-moz-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
-o-transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000);
transition: all 150ms cubic-bezier(0.770, 0.000, 0.175, 1.000); /* easeInOutQuart */
}
.invite-link {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
width: auto;
}
.settingIcon {
margin-left: 0.2rem;
}
body.modal-open {
overflow: hidden;
}
@mixin scut-link-unstyled {
&, &:visited, &:hover, &:active {
font-style: inherit;
color: inherit;
background-color: transparent;
font-size: inherit;
text-decoration: none;
font-variant: inherit;
font-weight: inherit;
line-height: inherit;
font-family: inherit;
}
}
%scut-link-unstyled {
@include scut-link-unstyled;
}
.text-button {
@extend %scut-link-unstyled;
}

View File

@ -138,3 +138,4 @@ $list-group-action-active-bg: $jf-blue-focus;
background-color: $success; background-color: $success;
} }
@import "../base.scss";

2
scss/bs4/bs4.scss Normal file
View File

@ -0,0 +1,2 @@
@import "../../node_modules/bootstrap4/scss/bootstrap";
@import "../base.scss";

View File

@ -138,3 +138,4 @@ $list-group-action-active-bg: $jf-blue-focus;
background-color: $success; background-color: $success;
} }
@import "../base.scss";

2
scss/bs5/bs5.scss Normal file
View File

@ -0,0 +1,2 @@
@import "../../node_modules/bootstrap/scss/bootstrap";
@import "../base.scss";

View File

@ -39,44 +39,45 @@ if not args.yes:
node_bin = input("input bin directory: ") node_bin = input("input bin directory: ")
for bsv in [d for d in local_path.iterdir() if "bs" in d.name]: for bsv in [d for d in local_path.iterdir() if "bs" in d.name]:
scss = bsv / f"{bsv.name}-jf.scss" scss = [(bsv / f"{bsv.name}-jf.scss"), (bsv / f"{bsv.name}.scss")]
css = bsv / f"{bsv.name}-jf.css" css = [(bsv / f"{bsv.name}-jf.css"), (bsv / f"{bsv.name}.css")]
min_css = bsv.parents[1] / "data" / "static" / f"{bsv.name}-jf.css" min_css = [(bsv.parents[1] / "data" / "static" / f"{bsv.name}-jf.css"), (bsv.parents[1] / "data" / "static" / f"{bsv.name}.css")]
with open(css, "w") as f: for i in range(2):
with open(css[i], "w") as f:
f.write( f.write(
sass.compile( sass.compile(
filename=str(scss.resolve()), output_style="expanded", precision=6 filename=str(scss[i].resolve()), output_style="expanded", precision=6
) )
) )
if css.exists(): if css[i].exists():
print(f"{bsv.name}: Compiled.") print(f"{scss[i].name}: Compiled.")
# postcss only excepts forwards slashes? weird. # postcss only excepts forwards slashes? weird.
cssPath = str(css.resolve()) cssPath = str(css[i].resolve())
if os.name == "nt": if os.name == "nt":
cssPath = cssPath.replace("\\", "/") cssPath = cssPath.replace("\\", "/")
runcmd( runcmd(
f'{str((node_bin / "postcss").resolve())} {cssPath} --replace --use autoprefixer' f'{str((node_bin / "postcss").resolve())} {cssPath} --replace --use autoprefixer'
) )
print(f"{bsv.name}: Prefixed.") print(f"{scss[i].name}: Prefixed.")
runcmd( runcmd(
f'{str((node_bin / "cleancss").resolve())} --level 1 --format breakWith=lf --output {str(min_css.resolve())} {str(css.resolve())}' f'{str((node_bin / "cleancss").resolve())} --level 1 --format breakWith=lf --output {str(min_css[i].resolve())} {str(css[i].resolve())}'
) )
if min_css.exists(): if min_css[i].exists():
print(f"{bsv.name}: Minified and copied to {str(min_css.resolve())}.") print(f"{scss[i].name}: Minified and copied to {str(min_css[i].resolve())}.")
for v in [("bootstrap", "bs5"), ("bootstrap4", "bs4")]: # for v in [("bootstrap", "bs5"), ("bootstrap4", "bs4")]:
new_path = str((local_path.parent / "data" / "static" / (v[1] + ".css")).resolve()) # new_path = str((local_path.parent / "data" / "static" / (v[1] + ".css")).resolve())
shutil.copy( # shutil.copy(
str( # str(
( # (
local_path.parent # local_path.parent
/ "node_modules" # / "node_modules"
/ v[0] # / v[0]
/ "dist" # / "dist"
/ "css" # / "css"
/ "bootstrap.min.css" # / "bootstrap.min.css"
).resolve() # ).resolve()
), # ),
new_path, # new_path,
) # )
print(f"Copied {v[1]} to {new_path}") # print(f"Copied {v[1]} to {new_path}")