diff --git a/app/common/Prefs.ts b/app/common/Prefs.ts index adc0c640..74584033 100644 --- a/app/common/Prefs.ts +++ b/app/common/Prefs.ts @@ -1,3 +1,12 @@ +import {StringUnion} from 'app/common/StringUnion'; + +export const SortPref = StringUnion("name", "date"); +export type SortPref = typeof SortPref.type; + +export const ViewPref = StringUnion("list", "icons"); +export type ViewPref = typeof ViewPref.type; + + // A collection of preferences related to a user or org (or combination). export interface Prefs { // TODO replace this with real preferences. @@ -5,5 +14,10 @@ export interface Prefs { } export type UserPrefs = Prefs; -export type UserOrgPrefs = Prefs; + +export interface UserOrgPrefs extends Prefs { + docMenuSort?: SortPref; + docMenuView?: ViewPref; +} + export type OrgPrefs = Prefs; diff --git a/app/common/StringUnion.ts b/app/common/StringUnion.ts index 4a783161..3abccb14 100644 --- a/app/common/StringUnion.ts +++ b/app/common/StringUnion.ts @@ -33,6 +33,13 @@ export const StringUnion = (...values: UnionType[]) => return value; }; - const unionNamespace = {guard, check, values}; + /** + * StringUnion.parse(value) returns value when it's valid, and undefined otherwise. + */ + const parse = (value: string|null|undefined): UnionType|undefined => { + return value != null && guard(value) ? value : undefined; + }; + + const unionNamespace = {guard, check, parse, values}; return Object.freeze(unionNamespace as typeof unionNamespace & {type: UnionType}); }; diff --git a/app/common/gristUrls.ts b/app/common/gristUrls.ts index 5aa7ce09..fd1bcf3c 100644 --- a/app/common/gristUrls.ts +++ b/app/common/gristUrls.ts @@ -153,7 +153,7 @@ export function encodeUrl(gristConfig: Partial, } else { parts.push(`doc/${encodeURIComponent(state.doc)}`); } - if (state.mode && parseOpenDocMode(state.mode)) { + if (state.mode && OpenDocMode.guard(state.mode)) { parts.push(`/m/${state.mode}`); } if (state.docPage) { @@ -235,19 +235,19 @@ export function decodeUrl(gristConfig: Partial, location: Locat } else { if (map.has('p')) { const p = map.get('p')!; - state.homePage = HomePage.guard(p) ? p : undefined; + state.homePage = HomePage.parse(p); } } - if (map.has('m')) { state.mode = parseOpenDocMode(map.get('m')!); } + if (map.has('m')) { state.mode = OpenDocMode.parse(map.get('m')); } if (sp.has('newui')) { state.newui = useNewUI(sp.get('newui') ? sp.get('newui') === '1' : undefined); } - if (map.has('billing')) { state.billing = parseBillingPage(map.get('billing')!); } - if (map.has('welcome')) { state.welcome = parseWelcomePage(map.get('welcome')!); } + if (map.has('billing')) { state.billing = BillingSubPage.parse(map.get('billing')) || 'billing'; } + if (map.has('welcome')) { state.welcome = WelcomePage.parse(map.get('welcome')) || 'user'; } if (sp.has('billingPlan')) { state.params!.billingPlan = sp.get('billingPlan')!; } if (sp.has('billingTask')) { - state.params!.billingTask = parseBillingTask(sp.get('billingTask')!); + state.params!.billingTask = BillingTask.parse(sp.get('billingTask')); } if (sp.has('style')) { - state.params!.style = parseInterfaceStyle(sp.get('style')!); + state.params!.style = InterfaceStyle.parse(sp.get('style')); } if (sp.has('embed')) { const embed = state.params!.embed = isAffirmative(sp.get('embed')); @@ -289,41 +289,6 @@ function parseDocPage(p: string) { return parseInt(p, 10); } -/** - * parseBillingPage ensures that the billing page value is a valid BillingPageType. - */ -function parseBillingPage(p: string): BillingPage { - return BillingSubPage.guard(p) ? p : 'billing'; -} - -/** - * parseBillingTask ensures that the value is a valid BillingTask or undefined. - */ -function parseBillingTask(t: string): BillingTask|undefined { - return BillingTask.guard(t) ? t : undefined; -} - -/** - * parseOpenDocMode ensures that the value is a valid OpenDocMode or undefined. - */ -function parseOpenDocMode(p: string): OpenDocMode|undefined { - return OpenDocMode.guard(p) ? p : undefined; -} - -/** - * parse welcome page ensure that the value is a valid WelcomePage, default to 'user' if not. - */ -function parseWelcomePage(p: string): WelcomePage { - return WelcomePage.guard(p) ? p : 'user'; -} - -/** - * Read interface style and make sure it is either valid or left undefined. - */ -function parseInterfaceStyle(t: string): InterfaceStyle|undefined { - return InterfaceStyle.guard(t) ? t : undefined; -} - /** * Parses the URL like "foo.bar.baz" into the pair {org: "foo", base: ".bar.baz"}. * Port is allowed and included into base. diff --git a/app/gen-server/lib/HomeDBManager.ts b/app/gen-server/lib/HomeDBManager.ts index d1941521..7f711718 100644 --- a/app/gen-server/lib/HomeDBManager.ts +++ b/app/gen-server/lib/HomeDBManager.ts @@ -1216,6 +1216,7 @@ export class HomeDBManager extends EventEmitter { const orgQuery = this.org(scope, orgKey, { manager, markPermissions, + needRealOrg: true }); const queryResult = await verifyIsPermitted(orgQuery); if (queryResult.status !== 200) { @@ -3198,11 +3199,11 @@ export class HomeDBManager extends EventEmitter { const prefs = this._normalizeQueryResults(subValue, childOptions); for (const pref of prefs) { if (pref.orgId && pref.userId) { - value['userOrgPrefs'] = pref.prefs; + value.userOrgPrefs = pref.prefs; } else if (pref.orgId) { - value['orgPrefs'] = pref.prefs; + value.orgPrefs = pref.prefs; } else if (pref.userId) { - value['userPrefs'] = pref.prefs; + value.userPrefs = pref.prefs; } } continue;