mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Replace time zone selector with one based on the newer autocomplete.
Summary: Flaky Dates test failures related to the use of JQuery autocomplete for time zones, which wasn't working well. This diff replaces that autocomplete (as well as a similar select box in DocumentSettings) with our newer autocomplete, adding some select-box like behavior. Most of the behavior is factored out into ACSelect, which could be more generally useful. Adds an option to autocomplete to keep options ordered according to their initial order. Unrelated: fix up usage of MultiHolder in Drafts to avoid 'already disposed' warnings. Test Plan: Fixed several affected tests. Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D2919
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import {loadUserManager} from 'app/client/lib/imports';
|
||||
import {loadGristDoc, loadUserManager} from 'app/client/lib/imports';
|
||||
import {AppModel, reportError} from 'app/client/models/AppModel';
|
||||
import {DocPageModel} from 'app/client/models/DocPageModel';
|
||||
import {getLoginOrSignupUrl, getLoginUrl, getLogoutUrl, urlState} from 'app/client/models/gristUrlState';
|
||||
import {showDocSettingsModal} from 'app/client/ui/DocumentSettings';
|
||||
import {showProfileModal} from 'app/client/ui/ProfileDialog';
|
||||
import {createUserImage} from 'app/client/ui/UserImage';
|
||||
import * as viewport from 'app/client/ui/viewport';
|
||||
@@ -82,7 +81,8 @@ export class AccountWidget extends Disposable {
|
||||
|
||||
// The 'Document Settings' item, when there is an open document.
|
||||
const documentSettingsItem = (gristDoc ?
|
||||
menuItem(() => showDocSettingsModal(gristDoc.docInfo, this._docPageModel!), 'Document Settings',
|
||||
menuItem(async () => (await loadGristDoc()).showDocSettingsModal(gristDoc.docInfo, this._docPageModel!),
|
||||
'Document Settings',
|
||||
testId('dm-doc-settings')) :
|
||||
null);
|
||||
|
||||
|
||||
@@ -2,49 +2,15 @@
|
||||
* This module export a component for editing some document settings consisting of the timezone,
|
||||
* (new settings to be added here ...).
|
||||
*/
|
||||
import { dom, IOptionFull, select, styled } from 'grainjs';
|
||||
import { dom, styled } from 'grainjs';
|
||||
import { Computed, Observable } from 'grainjs';
|
||||
|
||||
import { loadMomentTimezone, MomentTimezone } from 'app/client/lib/imports';
|
||||
import { loadMomentTimezone } from 'app/client/lib/imports';
|
||||
import { DocInfoRec } from 'app/client/models/DocModel';
|
||||
import { DocPageModel } from 'app/client/models/DocPageModel';
|
||||
import { testId, vars } from 'app/client/ui2018/cssVars';
|
||||
import { vars } from 'app/client/ui2018/cssVars';
|
||||
import { saveModal } from 'app/client/ui2018/modals';
|
||||
import { nativeCompare } from 'app/common/gutil';
|
||||
|
||||
/**
|
||||
* Returns the ordered list of offsets for names at time timestamp. See timezoneOptions for details
|
||||
* on the sorting order.
|
||||
*/
|
||||
// exported for testing
|
||||
export function timezoneOptionsImpl(
|
||||
timestamp: number, names: string[], moment: MomentTimezone
|
||||
): Array<IOptionFull<string>> {
|
||||
// What we want is moment(timestamp) but the dynamic import with our compiling settings produces
|
||||
// "moment is not a function". The following is equivalent, and easier than fixing import setup.
|
||||
const m = moment.unix(timestamp / 1000);
|
||||
|
||||
const options = names.map((value) => ({
|
||||
value,
|
||||
label: `(GMT${m.tz(value).format('Z')}) ${value}`,
|
||||
// A quick test reveal that it is a bit more efficient (~0.02ms) to get the offset using
|
||||
// `moment.tz.Zone#parse` than creating a Moment instance for each zone and then getting the
|
||||
// offset with `moment#utcOffset`.
|
||||
offset: -moment.tz.zone(value)!.parse(timestamp)
|
||||
}));
|
||||
options.sort((a, b) => nativeCompare(a.offset, b.offset) || nativeCompare(a.value, b.value));
|
||||
return options.map(({value, label}) => ({value, label}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array of IOptionFull<string> expected by `select` to create the list of timezones
|
||||
* options. The returned list is sorted based on the current offset (GMT-11:00 before GMT-10:00),
|
||||
* and then on alphabetical order of the name.
|
||||
*/
|
||||
function timezoneOptions(moment: MomentTimezone): Array<IOptionFull<string>> {
|
||||
return timezoneOptionsImpl(Date.now(), moment.tz.names(), moment);
|
||||
}
|
||||
|
||||
import { buildTZAutocomplete } from 'app/client/widgets/TZAutocomplete';
|
||||
|
||||
/**
|
||||
* Builds a simple saveModal for saving settings.
|
||||
@@ -59,7 +25,7 @@ export async function showDocSettingsModal(docInfo: DocInfoRec, docPageModel: Do
|
||||
cssDataRow("This document's ID (for API use):"),
|
||||
cssDataRow(dom('tt', docPageModel.currentDocId.get())),
|
||||
cssDataRow('Time Zone:'),
|
||||
cssDataRow(select(timezone, timezoneOptions(moment)), testId('ds-tz')),
|
||||
cssDataRow(dom.create(buildTZAutocomplete, moment, timezone, (val) => timezone.set(val))),
|
||||
],
|
||||
// At this point, we only need to worry about saving this one setting.
|
||||
saveFunc: () => docInfo.timezone.saveOnly(timezone.get()),
|
||||
|
||||
Reference in New Issue
Block a user