Skip to content
Merged
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
1 change: 1 addition & 0 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"columns": "columns",
"select_all": "Select all",
"clear": "Clear",
"copy": "Copy",
"docs": "Docs",
"team": "Team",
"host": "Host",
Expand Down
5 changes: 5 additions & 0 deletions public/locales/en/explore.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"sql": "Generated SQL",
"rest_api": "REST API",
"run_query": "Run Query",
"query_time": "Query time",
"apply_to_explore": "Apply to Explore",
"apply_to_explore_success": "Query applied to Explore. Click Run Query to execute.",
"apply_to_explore_error": "Could not apply query",
"copy": "Copy",
"export": "Export",
"new": "New",
"results": "Results",
Expand Down
1 change: 1 addition & 0 deletions public/locales/ru/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"columns": "столбцы",
"select_all": "Выбрать все",
"clear": "Очистить",
"copy": "Копировать",
"docs": "Документация",
"team": "Команда",
"host": "Хост",
Expand Down
5 changes: 5 additions & 0 deletions public/locales/ru/explore.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"sql": "Сгенерированный SQL",
"rest_api": "REST API",
"run_query": "Выполнить запрос",
"query_time": "Время запроса",
"apply_to_explore": "Применить к Explore",
"apply_to_explore_success": "Запрос применён к Explore. Нажмите «Выполнить запрос».",
"apply_to_explore_error": "Не удалось применить запрос",
"copy": "Копировать",
"export": "Экспорт",
"new": "Новый",
"results": "Результаты",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"columns": "列",
"select_all": "全选",
"clear": "清除",
"copy": "复制",
"docs": "文档",
"team": "团队",
"host": "主机",
Expand Down
5 changes: 5 additions & 0 deletions public/locales/zh/explore.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"sql": "生成的 SQL",
"rest_api": "REST API",
"run_query": "运行查询",
"query_time": "查询时间",
"apply_to_explore": "应用到 Explore",
"apply_to_explore_success": "查询已应用到 Explore。点击运行查询以执行。",
"apply_to_explore_error": "无法应用查询",
"copy": "复制",
"export": "导出",
"new": "新建",
"results": "结果",
Expand Down
41 changes: 41 additions & 0 deletions src/components/CodeEditor/index.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,47 @@
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

.infoBtn {
color: rgba(0, 0, 0, 0.45);
font-size: 16px;

&:hover {
color: #4a7faa;
}
}

.infoIcon {
margin-left: 6px;
color: #5a7a96;
font-size: 12px !important;

&:hover {
color: #3d6a95;
}
}

.infoList {
display: grid;
grid-template-columns: 140px 1fr;
gap: 8px 16px;
margin: 0;

dt {
color: rgba(0, 0, 0, 0.45);
font-weight: 600;
}

dd {
margin: 0;
word-break: break-all;
}
}

.infoMono {
font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
font-size: 12px;
}

.editorControls {
margin-bottom: 16px;
padding: 0 16px;
Expand Down
106 changes: 104 additions & 2 deletions src/components/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Col, Row, Space, Tooltip } from "antd";
import { Col, Modal, Row, Space, Tooltip } from "antd";
import Scrollbar from "react-custom-scrollbars";
import { CloseOutlined, SyncOutlined } from "@ant-design/icons";
import {
CloseOutlined,
InfoCircleOutlined,
SyncOutlined,
} from "@ant-design/icons";
import { Editor } from "@monaco-editor/react";
import { useTranslation } from "react-i18next";
import { useResponsive, useSize, useTrackedEffect } from "ahooks";
Expand All @@ -14,7 +18,9 @@ import Console from "@/components/Console";
import type { ConsoleError } from "@/components/Console";
import { MONACO_OPTIONS } from "@/utils/constants/monaco";
import type { Dataschema } from "@/types/dataschema";
import type { Member } from "@/types/team";
import equals from "@/utils/helpers/equals";
import formatTime from "@/utils/helpers/formatTime";
import { createCompletionProvider } from "@/utils/cubejs-language/completionProvider";
import { createDiagnosticProvider } from "@/utils/cubejs-language/diagnosticProvider";
import { createHoverProvider } from "@/utils/cubejs-language/hoverProvider";
Expand All @@ -23,6 +29,7 @@ import { parseYamlDocument } from "@/utils/cubejs-language/yamlParser";
import { parseJsDocument } from "@/utils/cubejs-language/jsParser";
import { CubeRegistry } from "@/utils/cubejs-language/registry";
import { isSmartGenerated, parseProvenance } from "@/utils/provenanceParser";
import CurrentUserStore from "@/stores/CurrentUserStore";

import SaveIcon from "@/assets/save.svg";

Expand All @@ -33,6 +40,29 @@ import styles from "./index.module.less";
import type { MergeStrategy } from "./RegenerateModal";
import type { FC } from "react";

const resolveSavedBy = (
schema: Dataschema | undefined,
members: Member[] | undefined,
currentUserId?: string,
currentUserName?: string | null
): string => {
if (!schema) return "—";

const fromRelation = schema.user?.display_name?.trim();
if (fromRelation) return fromRelation;

const member = members?.find((m) => m.user_id === schema.user_id);
const fromMember = member?.displayName?.trim() || member?.email?.trim() || "";
if (fromMember) return fromMember;

if (schema.user_id && schema.user_id === currentUserId) {
const self = currentUserName?.trim();
if (self) return self;
}

return "—";
};

interface CodeEditorProps {
schemas?: Dataschema[];
active?: string | null;
Expand All @@ -53,6 +83,8 @@ interface CodeEditorProps {
validationError: string | ConsoleError[];
cubeRegistry?: CubeRegistry;
onRefreshRegistry?: () => void;
branchName?: string;
versionNumber?: number;
}

const languages = {
Expand All @@ -76,8 +108,11 @@ const CodeEditor: FC<CodeEditorProps> = ({
validationError,
cubeRegistry,
onRefreshRegistry,
branchName,
versionNumber,
}) => {
const { t } = useTranslation(["models", "common"]);
const { teamData, currentUser } = CurrentUserStore();
const pageHeader = useRef(null);
const editorHeader = useRef(null);
const completionDisposableRef = useRef<any>(null);
Expand All @@ -95,6 +130,7 @@ const CodeEditor: FC<CodeEditorProps> = ({
);
const [showRegenerateModal, setShowRegenerateModal] =
useState<boolean>(false);
const [showInfoModal, setShowInfoModal] = useState<boolean>(false);

// Create a default registry if none provided
const registryRef = useRef<CubeRegistry>(cubeRegistry ?? new CubeRegistry());
Expand Down Expand Up @@ -587,6 +623,18 @@ const CodeEditor: FC<CodeEditorProps> = ({
onClick={() => onTabChange(files[name])}
>
{files[name].name} {files[name].code !== content?.[name] && "*"}
{active === name && (
<Tooltip title="Model info">
<InfoCircleOutlined
className={styles.infoIcon}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setShowInfoModal(true);
}}
/>
</Tooltip>
)}
<Tooltip title={t("common:words.close")}>
<CloseOutlined
className={styles.closeIcon}
Expand Down Expand Up @@ -704,6 +752,60 @@ const CodeEditor: FC<CodeEditorProps> = ({
</div>
)}
</div>
<Modal
title="Model info"
open={showInfoModal}
onCancel={() => setShowInfoModal(false)}
footer={null}
destroyOnClose
>
{files[active] && (
<dl className={styles.infoList}>
<dt>Name</dt>
<dd>{files[active].name}</dd>

<dt>Branch</dt>
<dd>{branchName || "—"}</dd>

<dt>Version</dt>
<dd>
{typeof versionNumber === "number" ? versionNumber : "—"}
</dd>

<dt>Saved by</dt>
<dd>
{resolveSavedBy(
files[active],
teamData?.members,
currentUser?.id,
currentUser?.displayName || currentUser?.email
)}
</dd>

<dt>Datasource</dt>
<dd>{files[active].datasource?.name || "—"}</dd>

<dt>Created at</dt>
<dd>
{files[active].created_at
? formatTime(files[active].created_at)
: "—"}
</dd>

<dt>Updated at</dt>
<dd>
{files[active].updated_at
? formatTime(files[active].updated_at)
: "—"}
</dd>

<dt>Checksum</dt>
<dd className={styles.infoMono}>
{files[active].checksum || "—"}
</dd>
</dl>
)}
</Modal>
<RegenerateModal
visible={showRegenerateModal}
onCancel={() => setShowRegenerateModal(false)}
Expand Down
Loading