diff --git a/ts/modules/accounts.ts b/ts/modules/accounts.ts
index 0d1a8b7..cbf6209 100644
--- a/ts/modules/accounts.ts
+++ b/ts/modules/accounts.ts
@@ -7,8 +7,6 @@ import { SearchConfiguration, QueryType, SearchableItem, SearchableItemDataAttri
import { HiddenInputField } from "./ui"
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;
const USER_DEFAULT_SORT_FIELD = "name";
@@ -976,9 +974,6 @@ export class accountsList extends PaginatedList {
});
this._populateNumbers();
- // FIXME: Remove!
- (window as any).acc = this;
-
let searchConfig: SearchConfiguration = {
filterArea: this._c.filterArea,
sortingByButton: this._sortingByButton,
diff --git a/ts/modules/activity.ts b/ts/modules/activity.ts
index 708199a..94af779 100644
--- a/ts/modules/activity.ts
+++ b/ts/modules/activity.ts
@@ -533,9 +533,6 @@ export class activityList extends PaginatedList {
}
});
- // FIXME: Remove!
- (window as any).act = this;
-
this._container = document.getElementById("activity-card-list")
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.
this._c.defaultSortAscending = this.ascending;
this._sortDirection.innerHTML = `${window.lang.strings("sortDirection")} `;
- // 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);
if (this._hasLoaded) {
if (this._search.inServerSearch) {
diff --git a/ts/modules/common.ts b/ts/modules/common.ts
index e417431..768591f 100644
--- a/ts/modules/common.ts
+++ b/ts/modules/common.ts
@@ -1,4 +1,5 @@
declare var window: GlobalWindow;
+import dateParser from "any-date-parser";
export function toDateString(date: Date): string {
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);
}
+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 => {
let req = new XMLHttpRequest();
if (window.pages) { url = window.pages.Base + url; }
diff --git a/ts/modules/list.ts b/ts/modules/list.ts
index 9b0d6a4..4c25366 100644
--- a/ts/modules/list.ts
+++ b/ts/modules/list.ts
@@ -4,6 +4,10 @@ import "@af-utils/scrollend-polyfill";
declare var window: GlobalWindow;
+export interface ListItem {
+ asElement: () => HTMLElement;
+};
+
export class RecordCounter {
private _container: HTMLElement;
private _totalRecords: HTMLElement;
@@ -342,7 +346,7 @@ export abstract class PaginatedList {
this.lastPage = resp.last_page;
appendFunc(resp);
-
+
this._counter.loaded = this._search.ordering.length;
if (post) post(resp);
diff --git a/ts/modules/search.ts b/ts/modules/search.ts
index 3b2a871..8d4d139 100644
--- a/ts/modules/search.ts
+++ b/ts/modules/search.ts
@@ -1,4 +1,5 @@
-const dateParser = require("any-date-parser");
+import { ListItem } from "./list";
+import { parseDateString } from "./common";
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 number> = (() => {
let m = new Map number>();
m.set("year", Date.prototype.getFullYear);
@@ -222,24 +209,15 @@ export class DateQuery extends Query {
${subject.name}: ${dateText != "" ? dateText+" " : ""}${value.text}
`;
}
+
public static paramsFromString(valueString: string): [ParsedDate, QueryOperator, boolean] {
- // FIXME: Validate this!
let op = QueryOperator.Equal;
if ((Object.values(QueryOperator) as string[]).includes(valueString.charAt(0))) {
op = valueString.charAt(0) as QueryOperator;
// Trim the operator from the string
valueString = valueString.substring(1);
}
-
- 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 out = parseDateString(valueString);
let isValid = true;
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;
- // FIXME: SearchableItem should really be ListItem or something, this isn't for search!
- asElement: () => HTMLElement;
}
export const SearchableItemDataAttribute = "data-search-item";
@@ -598,7 +574,6 @@ export class Search {
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 = () => {
// Generate filter buttons
for (let queryName of Object.keys(this._c.queries)) {
diff --git a/ts/typings/d.ts b/ts/typings/d.ts
index a1df5c8..e3c5a3c 100644
--- a/ts/typings/d.ts
+++ b/ts/typings/d.ts
@@ -161,5 +161,20 @@ interface PaginatedReqDTO {
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 modifiedConfig: Object;
diff --git a/usercache.go b/usercache.go
index 07e6868..b26be92 100644
--- a/usercache.go
+++ b/usercache.go
@@ -235,11 +235,12 @@ const (
}*/
type DateAttempt struct {
- Year *int `json:"year,omitempty"`
- Month *int `json:"month,omitempty"`
- Day *int `json:"day,omitempty"`
- Hour *int `json:"hour,omitempty"`
- Minute *int `json:"minute,omitempty"`
+ Year *int `json:"year,omitempty"`
+ Month *int `json:"month,omitempty"`
+ Day *int `json:"day,omitempty"`
+ Hour *int `json:"hour,omitempty"`
+ Minute *int `json:"minute,omitempty"`
+ OffsetMinutesFromUTC *int `json:"offsetMinutesFromUTC,omitempty"`
}
// Compare roughly compares a time.Time to a DateAttempt.
diff --git a/views.go b/views.go
index be574b4..c13191f 100644
--- a/views.go
+++ b/views.go
@@ -67,9 +67,10 @@ func (app *appContext) pushResources(gc *gin.Context, page Page) {
default:
toPush = []string{}
}
+ urlBase := app.getURLBase(gc)
if pusher := gc.Writer.Pusher(); pusher != nil {
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)
}
}
@@ -172,6 +173,10 @@ func (app *appContext) getLang(gc *gin.Context, page Page, chosen string) string
func (app *appContext) AdminPage(gc *gin.Context) {
app.pushResources(gc, AdminPage)
+
+ // Pre-emptively (maybe) generate user cache
+ go app.userCache.MaybeSync(app)
+
lang := app.getLang(gc, AdminPage, app.storage.lang.chosenAdminLang)
jfAdminOnly := app.config.Section("ui").Key("admin_only").MustBool(true)
jfAllowAll := app.config.Section("ui").Key("allow_all").MustBool(false)