Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ export abstract class AbstractChart {
abstract readonly type: ChartType;
protected readonly getters: CoreGetters;
readonly humanize: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;

constructor(definition: ChartDefinition, sheetId: UID, getters: CoreGetters) {
this.title = definition.title;
this.sheetId = sheetId;
this.getters = getters;
this.humanize = definition.humanize ?? true;
this.annotationText = definition.annotationText;
this.annotationLink = definition.annotationLink;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ export class ScorecardChart extends AbstractChart {
readonly baselineColorUp: Color;
readonly baselineColorDown: Color;
readonly fontColor?: Color;
readonly humanize: boolean;
readonly type = "scorecard";

constructor(definition: ScorecardChartDefinition, sheetId: UID, getters: CoreGetters) {
Expand All @@ -180,7 +179,6 @@ export class ScorecardChart extends AbstractChart {
this.background = definition.background;
this.baselineColorUp = definition.baselineColorUp ?? DEFAULT_SCORECARD_BASELINE_COLOR_UP;
this.baselineColorDown = definition.baselineColorDown ?? DEFAULT_SCORECARD_BASELINE_COLOR_DOWN;
this.humanize = definition.humanize ?? true;
}

static validateChartDefinition(
Expand All @@ -201,6 +199,8 @@ export class ScorecardChart extends AbstractChart {
baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
baseline: context.auxiliaryRange || "",
humanize: context.humanize,
annotationLink: context.annotationLink,
annotationText: context.annotationText,
};
}

Expand Down Expand Up @@ -287,6 +287,8 @@ export class ScorecardChart extends AbstractChart {
: undefined,
keyDescr: this.keyDescr,
humanize: this.humanize,
annotationText: this.annotationText,
annotationLink: this.annotationLink,
};
}

Expand Down
2 changes: 2 additions & 0 deletions packages/o-spreadsheet-engine/src/types/chart/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ export interface ChartCreationContext {
readonly treemapColoringOptions?: TreeMapColoringOptions;
readonly zoomable?: boolean;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export type ChartAxisFormats = { [axisId: string]: Format | undefined } | undefined;
Expand Down
2 changes: 2 additions & 0 deletions packages/o-spreadsheet-engine/src/types/chart/common_chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ export interface CommonChartDefinition {
readonly axesDesign?: AxesDesign;
readonly showValues?: boolean;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}
2 changes: 2 additions & 0 deletions packages/o-spreadsheet-engine/src/types/chart/funnel_chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface FunnelChartDefinition {
readonly funnelColors?: FunnelChartColors;
readonly cumulative?: boolean;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export type FunnelChartRuntime = {
Expand Down
2 changes: 2 additions & 0 deletions packages/o-spreadsheet-engine/src/types/chart/gauge_chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface GaugeChartDefinition {
readonly sectionRule: SectionRule;
readonly background?: Color;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export interface SectionRule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export interface ScorecardChartDefinition {
readonly baselineColorUp: Color;
readonly baselineColorDown: Color;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export type BaselineMode = "text" | "difference" | "percentage" | "progress";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface SunburstChartDefinition {
readonly groupColors?: (Color | undefined | null)[];
readonly pieHolePercentage?: number;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export type SunburstChartRuntime = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface TreeMapChartDefinition {
readonly valuesDesign?: TitleDesign;
readonly coloringOptions?: TreeMapColoringOptions;
readonly humanize?: boolean;
readonly annotationText?: string;
readonly annotationLink?: string;
}

export type TreeMapCategoryColorOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Store, useStore } from "../../../../store_engine";
import { UID } from "../../../../types";
import { FullScreenFigureStore } from "../../../full_screen_figure/full_screen_figure_store";
import { getBoundingRectAsPOJO } from "../../../helpers/dom_helpers";
import { InfoPopover, InfoState } from "../../../info_popover/info_popover";
import { MenuPopover, MenuState } from "../../../menu_popover/menu_popover";

interface Props {
Expand All @@ -25,13 +26,15 @@ interface MenuItem {

export class ChartDashboardMenu extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-ChartDashboardMenu";
static components = { MenuPopover };
static components = { MenuPopover, InfoPopover };
static props = { chartId: String, hasFullScreenButton: { type: Boolean, optional: true } };
static defaultProps = { hasFullScreenButton: true };

private fullScreenFigureStore!: Store<FullScreenFigureStore>;

private menuState: MenuState = useState({ isOpen: false, anchorRect: null, menuItems: [] });
private infoState: InfoState = useState({ isOpen: false, anchorRect: null });

setup() {
super.setup();
this.fullScreenFigureStore = useStore(FullScreenFigureStore);
Expand All @@ -53,6 +56,21 @@ export class ChartDashboardMenu extends Component<Props, SpreadsheetChildEnv> {
this.menuState.menuItems = getChartMenuActions(figureId, this.env);
}

showInfo(ev: MouseEvent) {
this.infoState.isOpen = true;
this.infoState.anchorRect = getBoundingRectAsPOJO(ev.currentTarget as HTMLElement);
}

getAnnotationText() {
const chart = this.env.model.getters.getChart(this.props.chartId);
return chart?.annotationText;
}

getAnnotationLink() {
const chart = this.env.model.getters.getChart(this.props.chartId);
return chart?.annotationLink;
}

get fullScreenMenuItem(): MenuItem | undefined {
if (!this.props.hasFullScreenButton) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,25 @@
<t t-if="item.preview" t-call="{{item.preview}}"/>
</div>
</t>
<div
class="o-figure-info-icon d-flex flex-row align-items-center align-middle text-muted me-2"
t-if="getAnnotationText() or getAnnotationLink()"
t-on-click="showInfo"
t-ref="infoButton">
<t t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
</div>
<button
class="o-chart-dashboard-item btn text-muted lh-1 p-1 fa fa-ellipsis-v"
t-on-click="openContextMenu"
/>
</div>
<InfoPopover
t-if="infoState.isOpen"
anchorRect="infoState.anchorRect"
onClose="() => this.infoState.isOpen=false"
infoText="getAnnotationText()"
infoLink="getAnnotationLink()"
/>
<MenuPopover
t-if="menuState.isOpen"
anchorRect="menuState.anchorRect"
Expand Down
6 changes: 6 additions & 0 deletions src/components/figures/figure/figure.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
}
}

.o-figure-info-icon {
margin-top: 2px;
width: 15px;
height: 15px;
}

div.o-figure-border {
z-index: 1;
border: 0px solid var(--os-figure-border-color);
Expand Down
20 changes: 19 additions & 1 deletion src/components/figures/figure/figure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from "../../../types/index";
import { getRefBoundingRect, keyboardEventToShortcutString } from "../../helpers/dom_helpers";
import { withZoom } from "../../helpers/zoom";
import { InfoPopover, InfoState } from "../../info_popover/info_popover";
import { MenuPopover, MenuState } from "../../menu_popover/menu_popover";

type ResizeAnchor =
Expand Down Expand Up @@ -49,17 +50,19 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
onMouseDown: { type: Function, optional: true },
onClickAnchor: { type: Function, optional: true },
};
static components = { MenuPopover };
static components = { MenuPopover, InfoPopover };
static defaultProps = {
onMouseDown: () => {},
onClickAnchor: () => {},
};

private menuState: MenuState = useState({ isOpen: false, anchorRect: null, menuItems: [] });
private infoState: InfoState = useState({ isOpen: false, anchorRect: null });

private figureRef = useRef("figure");
private figureWrapperRef = useRef("figureWrapper");
private menuButtonRef = useRef("menuButton");
private infoButtonRef = useRef("infoButton");

private borderWidth!: number;

Expand Down Expand Up @@ -280,4 +283,19 @@ export class FigureComponent extends Component<Props, SpreadsheetChildEnv> {
!this.env.model.getters.isCurrentSheetLocked()
);
}

showInfo() {
this.infoState.isOpen = true;
this.infoState.anchorRect = getRefBoundingRect(this.infoButtonRef);
}

getAnnotationText() {
const chart = this.env.model.getters.getChartFromFigureId(this.props.figureUI.id);
return chart?.annotationText;
}

getAnnotationLink() {
const chart = this.env.model.getters.getChartFromFigureId(this.props.figureUI.id);
return chart?.annotationLink;
}
}
15 changes: 15 additions & 0 deletions src/components/figures/figure/figure.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@
openContextMenu.bind="openContextMenu"
/>
<div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
<div
class="o-figure-info-icon d-flex flex-row align-items-center align-middle text-muted me-2"
t-if="getAnnotationText() or getAnnotationLink()"
t-on-click="showInfo"
t-ref="infoButton">
<t t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
</div>
<InfoPopover
t-if="infoState.isOpen"
anchorRect="infoState.anchorRect"
width="props.figureUI.width/2"
onClose="() => this.infoState.isOpen=false"
infoText="getAnnotationText()"
infoLink="getAnnotationLink()"
/>
<div
class="o-figure-menu-item d-flex-align-items-center"
t-if="!env.model.getters.isReadonly() and props.figureUI.tag !== 'carousel'"
Expand Down
21 changes: 21 additions & 0 deletions src/components/info_popover/info_popover.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.o-spreadsheet {
a.o-link-info {
font-size: 13px;
font-weight: bold;
justify-content: space-between;
height: var(--os-link-tooltip-height);
width: var(--os-link-tooltip-width);
line-height: 13px;
color: var(--os-link-color);
text-decoration: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

a.o-link-info:hover {
text-decoration: none;
color: var(--os-link-hover-color);
cursor: pointer;
}
}
64 changes: 64 additions & 0 deletions src/components/info_popover/info_popover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Pixel, Rect } from "@odoo/o-spreadsheet-engine";
import { MENU_WIDTH } from "@odoo/o-spreadsheet-engine/constants";
import { SpreadsheetChildEnv } from "@odoo/o-spreadsheet-engine/types/spreadsheet_env";
import { Component, useExternalListener } from "@odoo/owl";
import { PopoverPropsPosition } from "../../types/cell_popovers";
import { cssPropertiesToCss } from "../helpers";
import { Popover, PopoverProps } from "../popover";

interface Props {
anchorRect: Rect;
popoverPositioning: PopoverPropsPosition;
maxHeight?: Pixel;
width?: number;
onClose: () => void;
infoText?: string;
infoLink?: string;
}

export interface InfoState {
isOpen: boolean;
anchorRect: null | Rect;
}

export class InfoPopover extends Component<Props, SpreadsheetChildEnv> {
static template = "o-spreadsheet-Info-Popover";
static props = {
anchorRect: Object,
popoverPositioning: { type: String, optional: true },
maxHeight: { type: Number, optional: true },
width: { type: Number, optional: true },
onClose: Function,
infoText: { type: String, optional: true },
infoLink: { type: String, optional: true },
};

static components = { Popover };
static defaultProps = {
popoverPositioning: "top-right",
width: MENU_WIDTH,
};

setup() {
useExternalListener(window, "click", this.onExternalClick, { capture: true });
}

get popoverProps(): PopoverProps {
return {
anchorRect: this.props.anchorRect,
maxHeight: this.props.maxHeight,
positioning: "bottom-left",
verticalOffset: 0,
};
}

private onExternalClick() {
this.props.onClose();
}

get infoStyle() {
return this.props.width
? cssPropertiesToCss({ "max-width": this.props.width + "px", "min-width": MENU_WIDTH + "px" })
: "";
}
}
17 changes: 17 additions & 0 deletions src/components/info_popover/info_popover.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<templates>
<t t-name="o-spreadsheet-Info-Popover">
<Popover t-props="popoverProps">
<div class="bg-white overflow-auto p-2" t-att-style="infoStyle">
<div class="m-1" data-test-id="annotation-text" t-if="props.infoText">
<t t-foreach="props.infoText.split('\n')" t-as="line" t-key="line">
<t t-esc="line"/>
<br/>
</t>
</div>
<div class="m-1" t-if="props.infoLink">
<a class="o-link-info" t-att-href="props.infoLink">See more</a>
</div>
</div>
</Popover>
</t>
</templates>
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@
/>
</t>
</SidePanelCollapsible>
<ChartAnnotation t-props="this.props"/>
</t>
</templates>
Loading