diff --git a/app/client/components/ViewLayout.css b/app/client/components/ViewLayout.css index d341ae16..fdd381b2 100644 --- a/app/client/components/ViewLayout.css +++ b/app/client/components/ViewLayout.css @@ -24,21 +24,6 @@ background-color: var(--grist-theme-widget-bg, white); } -/* TODO should be switched to use new icon */ -.viewsection_drag_indicator { - visibility: hidden; - top: 1px; - width: 16px; - height: 16px; - margin: 0; - padding: 0px; -} - -.viewsection_title:hover .viewsection_drag_indicator.layout_grabbable { - visibility: visible; - z-index: 100; /* ensure it's above the resizer line, since it's hard to grab otherwise */ -} - .viewsection_btn { display: inline-block; padding: 0px 4px; diff --git a/app/client/components/ViewLayout.ts b/app/client/components/ViewLayout.ts index 4e543674..0a3af1f4 100644 --- a/app/client/components/ViewLayout.ts +++ b/app/client/components/ViewLayout.ts @@ -15,7 +15,7 @@ import {reportError} from 'app/client/models/errors'; import {filterBar} from 'app/client/ui/FilterBar'; import {viewSectionMenu} from 'app/client/ui/ViewSectionMenu'; import {buildWidgetTitle} from 'app/client/ui/WidgetTitle'; -import {isNarrowScreenObs, mediaSmall, testId, theme} from 'app/client/ui2018/cssVars'; +import {isNarrowScreenObs, colors, mediaSmall, testId, theme} from 'app/client/ui2018/cssVars'; import {icon} from 'app/client/ui2018/icons'; import {DisposableWithEvents} from 'app/common/DisposableWithEvents'; import {mod} from 'app/common/gutil'; @@ -294,7 +294,8 @@ export function buildViewSectionDom(options: { dom.cls('active_section', vs.hasFocus), dom.cls('active_section--no-indicator', !focusable), dom.maybe((use) => use(vs.viewInstance), (viewInstance) => dom('div.viewsection_title.flexhbox', - dom('span.viewsection_drag_indicator.glyphicon.glyphicon-option-vertical', + cssDragIcon('DragDrop', + dom.cls("viewsection_drag_indicator"), // Makes element grabbable only if grist is not readonly. dom.cls('layout_grabbable', (use) => !use(gristDoc.isReadonlyKo)), !draggable ? dom.style("visibility", "hidden") : null @@ -416,6 +417,18 @@ const cssLayoutBox = styled('div', ` } `); +// z-index ensure it's above the resizer line, since it's hard to grab otherwise +const cssDragIcon = styled(icon, ` + visibility: hidden; + --icon-color: ${colors.slate}; + top: -1px; + z-index: 100; + + .viewsection_title:hover &.layout_grabbable { + visibility: visible; + } +`); + // This class is added while sections are being resized (or otherwise edited), to ensure that the // content of the section (such as an iframe) doesn't interfere with mouse drag-related events. // (It assumes that contained elements do not set pointer-events to another value; if that were diff --git a/app/plugin/DocApiTypes.ts b/app/plugin/DocApiTypes.ts index ea9b8cb7..8f9fc049 100644 --- a/app/plugin/DocApiTypes.ts +++ b/app/plugin/DocApiTypes.ts @@ -1,4 +1,4 @@ -import { CellValue } from "app/plugin/GristData"; +import { CellValue } from "./GristData"; /** * JSON schema for api /record endpoint. Used in POST method for adding new records. diff --git a/app/plugin/TableOperations.ts b/app/plugin/TableOperations.ts index 065a7177..bf90d9f0 100644 --- a/app/plugin/TableOperations.ts +++ b/app/plugin/TableOperations.ts @@ -1,4 +1,4 @@ -import * as Types from 'app/plugin/DocApiTypes'; +import * as Types from './DocApiTypes'; /** * Offer CRUD-style operations on a table. diff --git a/app/plugin/TableOperationsImpl.ts b/app/plugin/TableOperationsImpl.ts index 22af81d8..27c0de43 100644 --- a/app/plugin/TableOperationsImpl.ts +++ b/app/plugin/TableOperationsImpl.ts @@ -1,6 +1,6 @@ -import * as Types from "app/plugin/DocApiTypes"; -import { BulkColValues } from 'app/plugin/GristData'; -import { OpOptions, TableOperations, UpsertOptions } from 'app/plugin/TableOperations'; +import * as Types from "./DocApiTypes"; +import { BulkColValues } from './GristData'; +import { OpOptions, TableOperations, UpsertOptions } from './TableOperations'; import { arrayRepeat } from './gutil'; import flatMap = require('lodash/flatMap'); import isEqual = require('lodash/isEqual'); diff --git a/app/plugin/objtypes.ts b/app/plugin/objtypes.ts index 40e651cb..f0c48cfd 100644 --- a/app/plugin/objtypes.ts +++ b/app/plugin/objtypes.ts @@ -4,7 +4,7 @@ */ // tslint:disable:max-classes-per-file -import { CellValue, GristObjCode } from 'app/plugin/GristData'; +import { CellValue, GristObjCode } from './GristData'; import isPlainObject = require('lodash/isPlainObject'); // The text to show on cells whose values are pending. diff --git a/app/server/lib/requestUtils.ts b/app/server/lib/requestUtils.ts index 34c93d2e..ab7243e3 100644 --- a/app/server/lib/requestUtils.ts +++ b/app/server/lib/requestUtils.ts @@ -117,7 +117,7 @@ export function matchesBaseDomain(domain: string, baseDomain: string) { } export function isEnvironmentAllowedHost(url: string|URL) { - const urlHost = (typeof url === 'string') ? url : url.host; + const urlHost = (typeof url === 'string') ? url : url.hostname; return (process.env.GRIST_ALLOWED_HOSTS || "").split(",").some(domain => domain && matchesBaseDomain(urlHost, domain) ); diff --git a/app/server/lib/sendAppPage.ts b/app/server/lib/sendAppPage.ts index 18ec1607..21740d12 100644 --- a/app/server/lib/sendAppPage.ts +++ b/app/server/lib/sendAppPage.ts @@ -157,7 +157,7 @@ function configuredPageTitleSuffix() { */ function getPageTitle(req: express.Request, config: GristLoadConfig): string { const maybeDoc = getDocFromConfig(config); - if (!maybeDoc) { return translate(req, 'sendAppPage.Loading') + "..."; } + if (!maybeDoc) { return translate(req, 'Loading') + "..."; } return handlebars.Utils.escapeExpression(maybeDoc.name); } diff --git a/test/server/lib/DocApi.ts b/test/server/lib/DocApi.ts index 9e6af838..0ec6feaa 100644 --- a/test/server/lib/DocApi.ts +++ b/test/server/lib/DocApi.ts @@ -3035,6 +3035,7 @@ function testDocApi() { await checkOrigin("https://www.toto.com", 403, "Unrecognized origin"); await checkOrigin("https://badexample.com", 403, "Unrecognized origin"); await checkOrigin("https://bad.com/example.com/toto", 403, "Unrecognized origin"); + await checkOrigin("https://example.com:3000/path", 200); await checkOrigin("https://example.com/path", 200); await checkOrigin("https://good.example.com/toto", 200); }); @@ -3133,7 +3134,7 @@ class TestServer { REDIS_URL: process.env.TEST_REDIS_URL, APP_HOME_URL: _homeUrl, ALLOWED_WEBHOOK_DOMAINS: `example.com,localhost:${webhooksTestPort}`, - GRIST_ALLOWED_HOSTS: `example.com,localhost:${webhooksTestPort}`, + GRIST_ALLOWED_HOSTS: `example.com,localhost`, ...process.env };