mirror of
https://github.com/hrfee/jfa-go.git
synced 2026-01-18 16:47:42 +01:00
list: cleanup, include offset in DateAttempt
included UTC offset in minutes in DateAttempt, will be used shortly. Also moved this stuff (ParsedDate, DateAttempt) to the common d.ts, and the method for parsing from a string (now parseDateString) to common. Also pre-emptively load the user cache when the admin page loads.
This commit is contained in:
@@ -7,8 +7,6 @@ import { SearchConfiguration, QueryType, SearchableItem, SearchableItemDataAttri
|
|||||||
import { HiddenInputField } from "./ui"
|
import { HiddenInputField } from "./ui"
|
||||||
import { PaginatedList } from "./list"
|
import { PaginatedList } from "./list"
|
||||||
|
|
||||||
// FIXME: Find and define a threshold after which searches are no longer performed on input (or just in general by the browser).
|
|
||||||
|
|
||||||
declare var window: GlobalWindow;
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
const USER_DEFAULT_SORT_FIELD = "name";
|
const USER_DEFAULT_SORT_FIELD = "name";
|
||||||
@@ -976,9 +974,6 @@ export class accountsList extends PaginatedList {
|
|||||||
});
|
});
|
||||||
this._populateNumbers();
|
this._populateNumbers();
|
||||||
|
|
||||||
// FIXME: Remove!
|
|
||||||
(window as any).acc = this;
|
|
||||||
|
|
||||||
let searchConfig: SearchConfiguration = {
|
let searchConfig: SearchConfiguration = {
|
||||||
filterArea: this._c.filterArea,
|
filterArea: this._c.filterArea,
|
||||||
sortingByButton: this._sortingByButton,
|
sortingByButton: this._sortingByButton,
|
||||||
|
|||||||
@@ -533,9 +533,6 @@ export class activityList extends PaginatedList {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: Remove!
|
|
||||||
(window as any).act = this;
|
|
||||||
|
|
||||||
this._container = document.getElementById("activity-card-list")
|
this._container = document.getElementById("activity-card-list")
|
||||||
document.addEventListener("activity-reload", () => this.reload());
|
document.addEventListener("activity-reload", () => this.reload());
|
||||||
|
|
||||||
@@ -583,7 +580,7 @@ export class activityList extends PaginatedList {
|
|||||||
// Setting default sort makes sense, since this is the only sort ever being done.
|
// Setting default sort makes sense, since this is the only sort ever being done.
|
||||||
this._c.defaultSortAscending = this.ascending;
|
this._c.defaultSortAscending = this.ascending;
|
||||||
this._sortDirection.innerHTML = `${window.lang.strings("sortDirection")} <i class="ri-arrow-${v ? "up" : "down"}-s-line ml-2"></i>`;
|
this._sortDirection.innerHTML = `${window.lang.strings("sortDirection")} <i class="ri-arrow-${v ? "up" : "down"}-s-line ml-2"></i>`;
|
||||||
// FIXME?: We don't actually re-sort the list here, instead just use setOrdering to apply this.ascending before a reload.
|
// NOTE: We don't actually re-sort the list here, instead just use setOrdering to apply this.ascending before a reload.
|
||||||
this._search.setOrdering(this._search.ordering, this._c.defaultSortField, this.ascending);
|
this._search.setOrdering(this._search.ordering, this._c.defaultSortField, this.ascending);
|
||||||
if (this._hasLoaded) {
|
if (this._hasLoaded) {
|
||||||
if (this._search.inServerSearch) {
|
if (this._search.inServerSearch) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
declare var window: GlobalWindow;
|
declare var window: GlobalWindow;
|
||||||
|
import dateParser from "any-date-parser";
|
||||||
|
|
||||||
export function toDateString(date: Date): string {
|
export function toDateString(date: Date): string {
|
||||||
const locale = window.language || (window as any).navigator.userLanguage || window.navigator.language;
|
const locale = window.language || (window as any).navigator.userLanguage || window.navigator.language;
|
||||||
@@ -21,6 +22,20 @@ export function toDateString(date: Date): string {
|
|||||||
return date.toLocaleDateString(locale, args1) + " " + date.toLocaleString(locale, args2);
|
return date.toLocaleDateString(locale, args1) + " " + date.toLocaleString(locale, args2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const parseDateString = (value: string): ParsedDate => {
|
||||||
|
let out: ParsedDate = {
|
||||||
|
text: value,
|
||||||
|
// Used just to tell use what fields the user passed.
|
||||||
|
attempt: dateParser.attempt(value),
|
||||||
|
// note Date.fromString is also provided by dateParser.
|
||||||
|
date: (Date as any).fromString(value) as Date
|
||||||
|
};
|
||||||
|
out.attempt.offsetMinutesFromUTC = out.date.getTimezoneOffset();
|
||||||
|
// Month in Date objects is 0-based, so make our parsed date that way too
|
||||||
|
if ("month" in out.attempt) out.attempt.month -= 1;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
export const _get = (url: string, data: Object, onreadystatechange: (req: XMLHttpRequest) => void, noConnectionError: boolean = false): void => {
|
||||||
let req = new XMLHttpRequest();
|
let req = new XMLHttpRequest();
|
||||||
if (window.pages) { url = window.pages.Base + url; }
|
if (window.pages) { url = window.pages.Base + url; }
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ import "@af-utils/scrollend-polyfill";
|
|||||||
|
|
||||||
declare var window: GlobalWindow;
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
|
export interface ListItem {
|
||||||
|
asElement: () => HTMLElement;
|
||||||
|
};
|
||||||
|
|
||||||
export class RecordCounter {
|
export class RecordCounter {
|
||||||
private _container: HTMLElement;
|
private _container: HTMLElement;
|
||||||
private _totalRecords: HTMLElement;
|
private _totalRecords: HTMLElement;
|
||||||
@@ -342,7 +346,7 @@ export abstract class PaginatedList {
|
|||||||
this.lastPage = resp.last_page;
|
this.lastPage = resp.last_page;
|
||||||
|
|
||||||
appendFunc(resp);
|
appendFunc(resp);
|
||||||
|
|
||||||
this._counter.loaded = this._search.ordering.length;
|
this._counter.loaded = this._search.ordering.length;
|
||||||
|
|
||||||
if (post) post(resp);
|
if (post) post(resp);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
const dateParser = require("any-date-parser");
|
import { ListItem } from "./list";
|
||||||
|
import { parseDateString } from "./common";
|
||||||
|
|
||||||
declare var window: GlobalWindow;
|
declare var window: GlobalWindow;
|
||||||
|
|
||||||
@@ -176,20 +177,6 @@ export class StringQuery extends Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DateAttempt {
|
|
||||||
year?: number;
|
|
||||||
month?: number;
|
|
||||||
day?: number;
|
|
||||||
hour?: number;
|
|
||||||
minute?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ParsedDate {
|
|
||||||
attempt: DateAttempt;
|
|
||||||
date: Date;
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const dateGetters: Map<string, () => number> = (() => {
|
const dateGetters: Map<string, () => number> = (() => {
|
||||||
let m = new Map<string, () => number>();
|
let m = new Map<string, () => number>();
|
||||||
m.set("year", Date.prototype.getFullYear);
|
m.set("year", Date.prototype.getFullYear);
|
||||||
@@ -222,24 +209,15 @@ export class DateQuery extends Query {
|
|||||||
<span class="font-bold mr-2">${subject.name}:</span> ${dateText != "" ? dateText+" " : ""}${value.text}
|
<span class="font-bold mr-2">${subject.name}:</span> ${dateText != "" ? dateText+" " : ""}${value.text}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static paramsFromString(valueString: string): [ParsedDate, QueryOperator, boolean] {
|
public static paramsFromString(valueString: string): [ParsedDate, QueryOperator, boolean] {
|
||||||
// FIXME: Validate this!
|
|
||||||
let op = QueryOperator.Equal;
|
let op = QueryOperator.Equal;
|
||||||
if ((Object.values(QueryOperator) as string[]).includes(valueString.charAt(0))) {
|
if ((Object.values(QueryOperator) as string[]).includes(valueString.charAt(0))) {
|
||||||
op = valueString.charAt(0) as QueryOperator;
|
op = valueString.charAt(0) as QueryOperator;
|
||||||
// Trim the operator from the string
|
// Trim the operator from the string
|
||||||
valueString = valueString.substring(1);
|
valueString = valueString.substring(1);
|
||||||
}
|
}
|
||||||
|
let out = parseDateString(valueString);
|
||||||
let out: ParsedDate = {
|
|
||||||
text: valueString,
|
|
||||||
// Used just to tell use what fields the user passed.
|
|
||||||
attempt: dateParser.attempt(valueString),
|
|
||||||
// note Date.fromString is also provided by dateParser.
|
|
||||||
date: (Date as any).fromString(valueString) as Date
|
|
||||||
};
|
|
||||||
// Month in Date objects is 0-based, so make our parsed date that way too
|
|
||||||
if ("month" in out.attempt) out.attempt.month -= 1;
|
|
||||||
let isValid = true;
|
let isValid = true;
|
||||||
if ("invalid" in (out.date as any)) { isValid = false; };
|
if ("invalid" in (out.date as any)) { isValid = false; };
|
||||||
|
|
||||||
@@ -278,10 +256,8 @@ export class DateQuery extends Query {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SearchableItem {
|
export interface SearchableItem extends ListItem {
|
||||||
matchesSearch: (query: string) => boolean;
|
matchesSearch: (query: string) => boolean;
|
||||||
// FIXME: SearchableItem should really be ListItem or something, this isn't for search!
|
|
||||||
asElement: () => HTMLElement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SearchableItemDataAttribute = "data-search-item";
|
export const SearchableItemDataAttribute = "data-search-item";
|
||||||
@@ -598,7 +574,6 @@ export class Search {
|
|||||||
this._c.search.oninput(null as any);
|
this._c.search.oninput(null as any);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Make XQuery classes less specifically for in-progress searches, and include this code for making info button things.
|
|
||||||
generateFilterList = () => {
|
generateFilterList = () => {
|
||||||
// Generate filter buttons
|
// Generate filter buttons
|
||||||
for (let queryName of Object.keys(this._c.queries)) {
|
for (let queryName of Object.keys(this._c.queries)) {
|
||||||
|
|||||||
@@ -161,5 +161,20 @@ interface PaginatedReqDTO {
|
|||||||
ascending: boolean;
|
ascending: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface DateAttempt {
|
||||||
|
year?: number;
|
||||||
|
month?: number;
|
||||||
|
day?: number;
|
||||||
|
hour?: number;
|
||||||
|
minute?: number;
|
||||||
|
offsetMinutesFromUTC?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ParsedDate {
|
||||||
|
attempt: DateAttempt;
|
||||||
|
date: Date;
|
||||||
|
text: string;
|
||||||
|
};
|
||||||
|
|
||||||
declare var config: Object;
|
declare var config: Object;
|
||||||
declare var modifiedConfig: Object;
|
declare var modifiedConfig: Object;
|
||||||
|
|||||||
11
usercache.go
11
usercache.go
@@ -235,11 +235,12 @@ const (
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
type DateAttempt struct {
|
type DateAttempt struct {
|
||||||
Year *int `json:"year,omitempty"`
|
Year *int `json:"year,omitempty"`
|
||||||
Month *int `json:"month,omitempty"`
|
Month *int `json:"month,omitempty"`
|
||||||
Day *int `json:"day,omitempty"`
|
Day *int `json:"day,omitempty"`
|
||||||
Hour *int `json:"hour,omitempty"`
|
Hour *int `json:"hour,omitempty"`
|
||||||
Minute *int `json:"minute,omitempty"`
|
Minute *int `json:"minute,omitempty"`
|
||||||
|
OffsetMinutesFromUTC *int `json:"offsetMinutesFromUTC,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare roughly compares a time.Time to a DateAttempt.
|
// Compare roughly compares a time.Time to a DateAttempt.
|
||||||
|
|||||||
7
views.go
7
views.go
@@ -67,9 +67,10 @@ func (app *appContext) pushResources(gc *gin.Context, page Page) {
|
|||||||
default:
|
default:
|
||||||
toPush = []string{}
|
toPush = []string{}
|
||||||
}
|
}
|
||||||
|
urlBase := app.getURLBase(gc)
|
||||||
if pusher := gc.Writer.Pusher(); pusher != nil {
|
if pusher := gc.Writer.Pusher(); pusher != nil {
|
||||||
for _, f := range toPush {
|
for _, f := range toPush {
|
||||||
if err := pusher.Push(PAGES.Base+f, nil); err != nil {
|
if err := pusher.Push(urlBase+f, nil); err != nil {
|
||||||
app.debug.Printf(lm.FailedServerPush, err)
|
app.debug.Printf(lm.FailedServerPush, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,6 +173,10 @@ func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string
|
|||||||
|
|
||||||
func (app *appContext) AdminPage(gc *gin.Context) {
|
func (app *appContext) AdminPage(gc *gin.Context) {
|
||||||
app.pushResources(gc, AdminPage)
|
app.pushResources(gc, AdminPage)
|
||||||
|
|
||||||
|
// Pre-emptively (maybe) generate user cache
|
||||||
|
go app.userCache.MaybeSync(app)
|
||||||
|
|
||||||
lang := app.getLang(gc, AdminPage, app.storage.lang.chosenAdminLang)
|
lang := app.getLang(gc, AdminPage, app.storage.lang.chosenAdminLang)
|
||||||
jfAdminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
|
jfAdminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
|
||||||
jfAllowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
|
jfAllowAll := app.config.Section("ui").Key("allow_all").MustBool(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user