mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Import redesign
Summary: New UI design for incremental imports. Test Plan: Updated Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3945
This commit is contained in:
@@ -16,7 +16,7 @@ import * as DocConfigTab from 'app/client/components/DocConfigTab';
|
||||
import {Drafts} from "app/client/components/Drafts";
|
||||
import {EditorMonitor} from "app/client/components/EditorMonitor";
|
||||
import * as GridView from 'app/client/components/GridView';
|
||||
import {Importer} from 'app/client/components/Importer';
|
||||
import {importFromFile, selectAndImport} from 'app/client/components/Importer';
|
||||
import {RawDataPage, RawDataPopup} from 'app/client/components/RawDataPage';
|
||||
import {ActionGroupWithCursorPos, UndoStack} from 'app/client/components/UndoStack';
|
||||
import {ViewLayout} from 'app/client/components/ViewLayout';
|
||||
@@ -423,11 +423,11 @@ export class GristDoc extends DisposableWithEvents {
|
||||
const importMenuItems = [
|
||||
{
|
||||
label: t("Import from file"),
|
||||
action: () => Importer.selectAndImport(this, importSourceElems, null, createPreview),
|
||||
action: () => importFromFile(this, createPreview),
|
||||
},
|
||||
...importSourceElems.map(importSourceElem => ({
|
||||
label: importSourceElem.importSource.label,
|
||||
action: () => Importer.selectAndImport(this, importSourceElems, importSourceElem, createPreview)
|
||||
action: () => selectAndImport(this, importSourceElems, importSourceElem, createPreview)
|
||||
}))
|
||||
];
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -68,7 +68,7 @@ export function buildParseOptionsForm(
|
||||
cssModalButtons(
|
||||
dom.domComputed((use) => items.every((item) => use(optionsMap.get(item.name)!) === values[item.name]),
|
||||
(unchanged) => (unchanged ?
|
||||
bigBasicButton('Back to preview', dom.on('click', doCancel), testId('parseopts-back')) :
|
||||
bigBasicButton('Close', dom.on('click', doCancel), testId('parseopts-back')) :
|
||||
bigPrimaryButton('Update preview', dom.on('click', () => doUpdate(collectParseOptions())),
|
||||
testId('parseopts-update'))
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { makeT } from 'app/client/lib/localization';
|
||||
import { bigBasicButton } from 'app/client/ui2018/buttons';
|
||||
import { testId } from 'app/client/ui2018/cssVars';
|
||||
import { testId, theme } from 'app/client/ui2018/cssVars';
|
||||
import { loadingSpinner } from 'app/client/ui2018/loaders';
|
||||
import { cssModalButtons, cssModalTitle, IModalControl, modal } from 'app/client/ui2018/modals';
|
||||
import { cssModalButtons, cssModalTitle, IModalControl, IModalOptions, modal } from 'app/client/ui2018/modals';
|
||||
import { PluginInstance } from 'app/common/PluginInstance';
|
||||
import { RenderTarget } from 'app/plugin/RenderOptions';
|
||||
import { Disposable, dom, DomContents, Observable, styled } from 'grainjs';
|
||||
@@ -15,6 +15,7 @@ const t = makeT('PluginScreen');
|
||||
export interface RenderOptions {
|
||||
// Maximizes modal to fill the viewport.
|
||||
fullscreen?: boolean;
|
||||
fullbody?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,6 +25,7 @@ export class PluginScreen extends Disposable {
|
||||
private _openModalCtl: IModalControl | null = null;
|
||||
private _importerContent = Observable.create<DomContents>(this, null);
|
||||
private _fullscreen = Observable.create(this, false);
|
||||
private _fullbody = Observable.create(this, false);
|
||||
|
||||
constructor(private _title: string) {
|
||||
super();
|
||||
@@ -46,13 +48,15 @@ export class PluginScreen extends Disposable {
|
||||
}
|
||||
|
||||
public render(content: DomContents, options?: RenderOptions) {
|
||||
this._fullscreen.set(Boolean(options?.fullscreen));
|
||||
this._fullbody.set(Boolean(options?.fullbody));
|
||||
this.showImportDialog();
|
||||
this._importerContent.set(content);
|
||||
this._fullscreen.set(Boolean(options?.fullscreen));
|
||||
}
|
||||
|
||||
// The importer state showing just an error.
|
||||
public renderError(message: string) {
|
||||
this._fullbody.set(false);
|
||||
this.render([
|
||||
this._buildModalTitle(),
|
||||
cssModalBody(t("Import failed: "), message, testId('importer-error')),
|
||||
@@ -66,6 +70,7 @@ export class PluginScreen extends Disposable {
|
||||
// The importer state showing just a spinner, when the user has to wait. We don't even let the
|
||||
// user cancel it, because the cleanup can only happen properly once the wait completes.
|
||||
public renderSpinner() {
|
||||
this._fullbody.set(false);
|
||||
this.render([this._buildModalTitle(), cssSpinner(loadingSpinner())]);
|
||||
}
|
||||
|
||||
@@ -74,19 +79,28 @@ export class PluginScreen extends Disposable {
|
||||
this._openModalCtl = null;
|
||||
}
|
||||
|
||||
public showImportDialog() {
|
||||
public showImportDialog(options?: IModalOptions) {
|
||||
if (this._openModalCtl) { return; }
|
||||
modal((ctl) => {
|
||||
modal((ctl, ctlOwner) => {
|
||||
this._openModalCtl = ctl;
|
||||
|
||||
// Make sure we are close when parent is closed.
|
||||
this.onDispose(() => {
|
||||
if (ctlOwner.isDisposed()) { return; }
|
||||
ctl.close();
|
||||
});
|
||||
|
||||
return [
|
||||
cssModalOverrides.cls(''),
|
||||
cssModalOverrides.cls('-fullscreen', this._fullscreen),
|
||||
cssModalOverrides.cls('-fullbody', this._fullbody),
|
||||
dom.domComputed(this._importerContent),
|
||||
testId('importer-dialog'),
|
||||
];
|
||||
}, {
|
||||
noClickAway: true,
|
||||
noEscapeKey: true,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -108,6 +122,11 @@ const cssModalOverrides = styled('div', `
|
||||
height: 100%;
|
||||
margin: 32px;
|
||||
}
|
||||
|
||||
&-fullbody {
|
||||
padding: 0px;
|
||||
background-color: ${theme.importerOutsideBg};
|
||||
}
|
||||
`);
|
||||
|
||||
const cssModalBody = styled('div', `
|
||||
|
||||
Reference in New Issue
Block a user