mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) updates from grist-core
This commit is contained in:
@@ -105,6 +105,13 @@ export class AdminPanel extends Disposable {
|
||||
value: this._buildSandboxingDisplay(owner),
|
||||
expandedContent: this._buildSandboxingNotice(),
|
||||
}),
|
||||
dom.create(AdminSectionItem, {
|
||||
id: 'authentication',
|
||||
name: t('Authentication'),
|
||||
description: t('Current authentication method'),
|
||||
value: this._buildAuthenticationDisplay(owner),
|
||||
expandedContent: this._buildAuthenticationNotice(owner),
|
||||
})
|
||||
]),
|
||||
|
||||
dom.create(AdminSection, t('Version'), [
|
||||
@@ -156,6 +163,37 @@ isolated from other documents and isolated from the network.'),
|
||||
];
|
||||
}
|
||||
|
||||
private _buildAuthenticationDisplay(owner: IDisposableOwner) {
|
||||
return dom.domComputed(
|
||||
use => {
|
||||
const req = this._checks.requestCheckById(use, 'authentication');
|
||||
const result = req ? use(req.result) : undefined;
|
||||
if (!result) {
|
||||
return cssValueLabel(cssErrorText('unavailable'));
|
||||
}
|
||||
|
||||
const { success, details } = result;
|
||||
const loginSystemId = details?.loginSystemId;
|
||||
|
||||
if (!success || !loginSystemId) {
|
||||
return cssValueLabel(cssErrorText('auth error'));
|
||||
}
|
||||
|
||||
if (loginSystemId === 'no-logins') {
|
||||
return cssValueLabel(cssDangerText('no authentication'));
|
||||
}
|
||||
|
||||
return cssValueLabel(cssHappyText(loginSystemId));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _buildAuthenticationNotice(owner: IDisposableOwner) {
|
||||
return t('Grist allows different types of authentication to be configured, including SAML and OIDC. \
|
||||
We recommend enabling one of these if Grist is accessible over the network or being made available \
|
||||
to multiple people.');
|
||||
}
|
||||
|
||||
private _buildUpdates(owner: MultiHolder) {
|
||||
// We can be in those states:
|
||||
enum State {
|
||||
@@ -446,6 +484,10 @@ const cssErrorText = styled('span', `
|
||||
color: ${theme.errorText};
|
||||
`);
|
||||
|
||||
export const cssDangerText = styled('div', `
|
||||
color: ${theme.dangerText};
|
||||
`);
|
||||
|
||||
const cssHappyText = styled('span', `
|
||||
color: ${theme.controlFg};
|
||||
`);
|
||||
|
||||
@@ -124,6 +124,7 @@ const cssItemName = styled('div', `
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 14px;
|
||||
font-size: ${vars.largeFontSize};
|
||||
padding-left: 24px;
|
||||
&-prefixed {
|
||||
|
||||
@@ -130,7 +130,10 @@ export function columnFilterMenu(owner: IDisposableOwner, opts: IFilterMenuOptio
|
||||
dom.onDispose(() => cancel ? doCancel() : doSave()),
|
||||
dom.onKeyDown({
|
||||
Enter: () => onClose(),
|
||||
Escape: () => onClose(),
|
||||
Escape: () => {
|
||||
cancel = true;
|
||||
onClose();
|
||||
},
|
||||
}),
|
||||
|
||||
// Filter by range
|
||||
|
||||
@@ -146,6 +146,14 @@ export function createHomeLeftPane(leftPanelOpen: Observable<boolean>, home: Hom
|
||||
) : null
|
||||
),
|
||||
createHelpTools(home.app),
|
||||
(commonUrls.termsOfService ?
|
||||
cssPageEntry(
|
||||
cssPageLink(cssPageIcon('Memo'), cssLinkText(t("Terms of service")),
|
||||
{ href: commonUrls.termsOfService, target: '_blank' },
|
||||
testId('dm-tos'),
|
||||
),
|
||||
) : null
|
||||
),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
@@ -205,7 +205,7 @@ export function buildPageWidgetPicker(
|
||||
// If savePromise throws an error, before or after timeout, we let the error propagate as it
|
||||
// should be handle by the caller.
|
||||
if (await isLongerThan(savePromise, DELAY_BEFORE_SPINNER_MS)) {
|
||||
const label = getWidgetTypes(type).label;
|
||||
const label = getWidgetTypes(type).getLabel();
|
||||
await spinnerModal(t("Building {{- label}} widget", { label }), savePromise);
|
||||
}
|
||||
}
|
||||
@@ -317,12 +317,12 @@ export class PageWidgetSelect extends Disposable {
|
||||
cssPanel(
|
||||
header(t("Select Widget")),
|
||||
sectionTypes.map((value) => {
|
||||
const {label, icon: iconName} = getWidgetTypes(value);
|
||||
const widgetInfo = getWidgetTypes(value);
|
||||
const disabled = computed(this._value.table, (use, tid) => this._isTypeDisabled(value, tid));
|
||||
return cssEntry(
|
||||
dom.autoDispose(disabled),
|
||||
cssTypeIcon(iconName),
|
||||
label,
|
||||
cssTypeIcon(widgetInfo.icon),
|
||||
widgetInfo.getLabel(),
|
||||
dom.on('click', () => !disabled.get() && this._selectType(value)),
|
||||
cssEntry.cls('-selected', (use) => use(this._value.type) === value),
|
||||
cssEntry.cls('-disabled', disabled),
|
||||
|
||||
@@ -38,7 +38,7 @@ import {PredefinedCustomSectionConfig} from "app/client/ui/PredefinedCustomSecti
|
||||
import {cssLabel} from 'app/client/ui/RightPanelStyles';
|
||||
import {linkId, NoLink, selectBy} from 'app/client/ui/selectBy';
|
||||
import {VisibleFieldsConfig} from 'app/client/ui/VisibleFieldsConfig';
|
||||
import {getTelemetryWidgetTypeFromVS, widgetTypesMap} from "app/client/ui/widgetTypesMap";
|
||||
import {getTelemetryWidgetTypeFromVS, getWidgetTypes} from "app/client/ui/widgetTypesMap";
|
||||
import {basicButton, primaryButton} from 'app/client/ui2018/buttons';
|
||||
import {buttonSelect} from 'app/client/ui2018/buttonSelect';
|
||||
import {labeledSquareCheckbox} from 'app/client/ui2018/checkbox';
|
||||
@@ -220,10 +220,10 @@ export class RightPanel extends Disposable {
|
||||
|
||||
private _buildStandardHeader() {
|
||||
return dom.maybe(this._pageWidgetType, (type) => {
|
||||
const widgetInfo = widgetTypesMap.get(type) || {label: 'Table', icon: 'TypeTable'};
|
||||
const widgetInfo = getWidgetTypes(type);
|
||||
const fieldInfo = getFieldType(type);
|
||||
return [
|
||||
cssTopBarItem(cssTopBarIcon(widgetInfo.icon), widgetInfo.label,
|
||||
cssTopBarItem(cssTopBarIcon(widgetInfo.icon), widgetInfo.getLabel(),
|
||||
cssTopBarItem.cls('-selected', (use) => use(this._topTab) === 'pageWidget'),
|
||||
dom.on('click', () => this._topTab.set("pageWidget")),
|
||||
testId('right-tab-pagewidget')),
|
||||
|
||||
@@ -3,21 +3,25 @@ import {ViewSectionRec} from "app/client/models/entities/ViewSectionRec";
|
||||
import {IPageWidget} from "app/client/ui/PageWidgetPicker";
|
||||
import {IconName} from "app/client/ui2018/IconList";
|
||||
import {IWidgetType} from "app/common/widgetTypes";
|
||||
import {makeT} from 'app/client/lib/localization';
|
||||
|
||||
const t = makeT('widgetTypesMap');
|
||||
|
||||
export const widgetTypesMap = new Map<IWidgetType, IWidgetTypeInfo>([
|
||||
['record', {label: 'Table', icon: 'TypeTable'}],
|
||||
['single', {label: 'Card', icon: 'TypeCard'}],
|
||||
['detail', {label: 'Card List', icon: 'TypeCardList'}],
|
||||
['chart', {label: 'Chart', icon: 'TypeChart'}],
|
||||
['form', {label: 'Form', icon: 'Board'}],
|
||||
['custom', {label: 'Custom', icon: 'TypeCustom'}],
|
||||
['custom.calendar', {label: 'Calendar', icon: 'TypeCalendar'}],
|
||||
['record', {name: 'Table', icon: 'TypeTable', getLabel: () => t('Table')}],
|
||||
['single', {name: 'Card', icon: 'TypeCard', getLabel: () => t('Card')}],
|
||||
['detail', {name: 'Card List', icon: 'TypeCardList', getLabel: () => t('Card List')}],
|
||||
['chart', {name: 'Chart', icon: 'TypeChart', getLabel: () => t('Chart')}],
|
||||
['form', {name: 'Form', icon: 'Board', getLabel: () => t('Form')}],
|
||||
['custom', {name: 'Custom', icon: 'TypeCustom', getLabel: () => t('Custom')}],
|
||||
['custom.calendar', {name: 'Calendar', icon: 'TypeCalendar', getLabel: () => t('Calendar')}],
|
||||
]);
|
||||
|
||||
// Widget type info.
|
||||
export interface IWidgetTypeInfo {
|
||||
label: string;
|
||||
name: string;
|
||||
icon: IconName;
|
||||
getLabel: () => string;
|
||||
}
|
||||
|
||||
// Returns the widget type info for sectionType, or the one for 'record' if sectionType is null.
|
||||
@@ -46,7 +50,7 @@ export function getTelemetryWidgetTypeFromPageWidget(widget: IPageWidget) {
|
||||
}
|
||||
|
||||
function getTelemetryWidgetType(type: IWidgetType, options: GetTelemetryWidgetTypeOptions = {}) {
|
||||
let telemetryWidgetType: string | undefined = widgetTypesMap.get(type)?.label;
|
||||
let telemetryWidgetType: string | undefined = widgetTypesMap.get(type)?.name;
|
||||
if (!telemetryWidgetType) { return undefined; }
|
||||
|
||||
if (options.isNewTable) {
|
||||
|
||||
Reference in New Issue
Block a user