Open kirin-ri opened 4 months ago
Error
The name 'cpu_cost' does not refer to any known table, tabular variable or function.
let cpu_rate_per_core_hour = 0.048; // 1 vCPUあたりの料金(USD/時間)
let mem_rate_per_gb_hour = 0.012; // 1 GiB RAMあたりの料金(USD/時間)
// 各名前空間のCPU使用量の料金計算
let cpu_cost = KubePodInventory
| summarize AvgCPU=avg(TotalCpuUsageNanoCores) by Namespace
| extend CPUHours = AvgCPU * (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / 1e9
| extend CPUCost = CPUHours * cpu_rate_per_core_hour;
// 各名前空間のメモリ使用量の料金計算
let mem_cost = KubePodInventory
| summarize AvgMemory=avg(TotalMemoryUsageBytes) by Namespace
| extend MemoryHours = AvgMemory * (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / (1024 * 1024 * 1024)
| extend MemoryCost = MemoryHours * mem_rate_per_gb_hour;
// CPUとメモリの料金を統合
cpu_cost
| join kind=inner (mem_cost) on Namespace
| project Namespace, CPUCost, MemoryCost, TotalCost = CPUCost + MemoryCost
let cpu_rate_per_core_hour = 0.048; // 1 vCPUあたりの料金(USD/時間) let mem_rate_per_gb_hour = 0.012; // 1 GiB RAMあたりの料金(USD/時間)
// 各名前空間のCPU使用量の料金計算 let cpu_cost = KubePodInventory | summarize AvgCPU=avg(TotalCpuUsageNanoCores) by Namespace | extend CPUHours = AvgCPU (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / 1e9 | extend CPUCost = CPUHours cpu_rate_per_core_hour;
// 各名前空間のメモリ使用量の料金計算 let mem_cost = KubePodInventory | summarize AvgMemory=avg(TotalMemoryUsageBytes) by Namespace | extend MemoryHours = AvgMemory (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / (1024 1024 1024) | extend MemoryCost = MemoryHours mem_rate_per_gb_hour;
// CPUとメモリの料金を統合 cpu_cost | join kind=inner (mem_cost) on Namespace | project Namespace, CPUCost, MemoryCost, TotalCost = CPUCost + MemoryCost
let cpu_rate_per_core_hour = 0.048; // 1 vCPUあたりの料金(USD/時間) let mem_rate_per_gb_hour = 0.012; // 1 GiB RAMあたりの料金(USD/時間)
// 各名前空間のCPU使用量の料金計算 let cpu_cost = KubePodInventory | where TimeGenerated >= ago(30d) | summarize AvgCPU=avg(CpuUsageNanoCores) by Namespace | extend CPUHours = AvgCPU (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / 1e9 | extend CPUCost = CPUHours cpu_rate_per_core_hour;
// 各名前空間のメモリ使用量の料金計算 let mem_cost = KubePodInventory | where TimeGenerated >= ago(30d) | summarize AvgMemory=avg(MemoryUsageBytes) by Namespace | extend MemoryHours = AvgMemory (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / (1024 1024 1024) | extend MemoryCost = MemoryHours mem_rate_per_gb_hour;
// CPUとメモリの料金を統合 cpu_cost | join kind=inner (mem_cost) on Namespace | project Namespace, CPUCost, MemoryCost, TotalCost = CPUCost + MemoryCost
TenantId c88bf5c1-8f71-4cea-ac74-f7c80746b79e SourceSystem Containers TimeGenerated [UTC] 2024-07-24T01:19:58Z Computer aks-nodepool1-20355066-vmss000003 ClusterId /subscriptions/234a74a7-bd43-4159-906b-bee68f8574be/resourceGroups/rg-i-dna-aks/providers/Microsoft.ContainerService/managedClusters/I-DNA-Cluster ContainerCreationTimeStamp [UTC] 2024-03-22T07:37:02Z PodUid f5da154d-a68a-4d2d-a9c9-03a18afa0cc6 PodCreationTimeStamp [UTC] 2024-03-22T07:36:54Z ContainerRestartCount 0 PodRestartCount 0 PodStartTime [UTC] 2024-03-22T07:36:54Z ControllerKind DaemonSet ControllerName csi-blob-node ContainerStatus running ContainerID cce984b8b3981ebc47dd752747a2458870c3654ef088a7323ce6751e4b930a3e ContainerName f5da154d-a68a-4d2d-a9c9-03a18afa0cc6/blob Name csi-blob-node-9lfwz PodLabel [{"app":"csi-blob-node","controller-revision-hash":"6fb8776f9d","kubernetes.azure.com\/managedby":"aks","pod-template-generation":"1"}] Namespace kube-system PodStatus Running ClusterName I-DNA-Cluster PodIp 10.224.0.4 ContainerLastStatus {} Type KubePodInventory _ResourceId /subscriptions/234a74a7-bd43-4159-90
KubePodInventory | distinct ContainerID, Namespace | join kind=innerunique ( ContainerLog | where _IsBillable == true | summarize BillableDataBytes = sum(_BilledSize) by ContainerID ) on ContainerID | union ( KubePodInventory | distinct ContainerID, Namespace | join kind=innerunique ( ContainerLogV2 | project-rename ContainerID = ContainerId | where _IsBillable == true | summarize BillableDataBytes = sum(_BilledSize) by ContainerID ) on ContainerID ) | summarize Total=sum(BillableDataBytes) by Namespace | render piechart
import subprocess
import pandas as pd
# 名前空間を指定
namespace = "<your-namespace>"
# kubectlコマンドを実行してリソース使用量を取得
kubectl_command = f"kubectl top pod --namespace {namespace}"
result = subprocess.run(kubectl_command.split(), capture_output=True, text=True)
# コマンド出力を処理
data = []
lines = result.stdout.split("\n")
for line in lines[1:]:
if line:
parts = line.split()
pod_name = parts[0]
cpu_usage = parts[1]
memory_usage = parts[2]
data.append({"pod_name": pod_name, "cpu_usage": cpu_usage, "memory_usage": memory_usage})
# データフレームに変換
df = pd.DataFrame(data)
# 単位変換 (mCPU to CPU, Mi to GiB)
df['cpu_usage'] = df['cpu_usage'].apply(lambda x: float(x.replace('m', '')) / 1000)
df['memory_usage'] = df['memory_usage'].apply(lambda x: float(x.replace('Mi', '')) / 1024)
# 料金計算用のレート (仮定の値を使用)
cpu_rate_per_core_hour = 0.048 # 1 vCPUあたりの料金(USD/時間)
mem_rate_per_gb_hour = 0.012 # 1 GiB RAMあたりの料金(USD/時間)
# 使用時間を仮定 (1時間の使用量)
usage_hours = 1
# CPUとメモリのコストを計算
df['cpu_cost'] = df['cpu_usage'] * cpu_rate_per_core_hour * usage_hours
df['memory_cost'] = df['memory_usage'] * mem_rate_per_gb_hour * usage_hours
# 合計コストを計算
df['total_cost'] = df['cpu_cost'] + df['memory_cost']
# 名前空間ごとのコストを集計
namespace_costs = df.sum()
print(namespace_costs)
(base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az aks update --resource-group rg-i-dna-aks --name I-DNA-Cluster --enable-cost-analysis
unrecognized arguments: --enable-cost-analysis
Examples from AI knowledge base:
az aks update --resource-group MyResourceGroup --name MyManagedCluster --load-balancer-managed-outbound-ip-count 2
Update a kubernetes cluster with standard SKU load balancer to use two AKS created IPs for the load balancer outbound connection usage.
az aks update --resource-group MyResourceGroup --name MyManagedCluster --api-server-authorized-ip-ranges 0.0.0.0/32
Restrict apiserver traffic in a kubernetes cluster to agentpool nodes.
az version
Show the versions of Azure CLI modules and extensions in JSON format by default or format configured by --output (autogenerated)
https://docs.microsoft.com/en-US/cli/azure/aks#az_aks_update
Read more about the command in reference docs
表示するコスト データがありません クラスターでコスト分析アドオンが有効になっていることを確認してください。アドオンが有効になっている場合は、正しいフィルターが選択されていることを確認してください。
az aks enable-addons --resource-group
(base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az aks enable-addons --resource-group rg-i-dna-aks --name I-DNA-Cluster --addons cost-management Invalid addon name: cost-management. (base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az aks update --resource-group rg-i-dna-aks --name I-DNA-Cluster --enable-cost-analysis unrecognized arguments: --enable-cost-analysis
az monitor log-analytics workspace list --resource-group
(base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az monitor log-analytics workspace list --resource-group --query "[].{Name:name, ID:id}" -o table argument --resource-group/-g: expected one argument
az monitor log-analytics workspace list --resource-group rg-i-dna-aks --query "[].{Name:name, ID:id}" -o table
az monitor log-analytics workspace create --resource-group rg-i-dna-aks --workspace-name myLogAnalyticsWorkspace
(base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az aks update --resource-group rg-i-dna-aks --name I-DNA-Cluster --enable-cost-analysis unrecognized arguments: --enable-cost-analysis
Examples from AI knowledge base: az aks update --resource-group MyResourceGroup --name MyManagedCluster --load-balancer-managed-outbound-ip-count 2 Update a kubernetes cluster with standard SKU load balancer to use two AKS created IPs for the load balancer outbound connection usage.
az aks update --resource-group MyResourceGroup --name MyManagedCluster --api-server-authorized-ip-ranges 0.0.0.0/32 Restrict apiserver traffic in a kubernetes cluster to agentpool nodes.
az version Show the versions of Azure CLI modules and extensions in JSON format by default or format configured by --output (autogenerated)
https://docs.microsoft.com/en-US/cli/azure/aks#az_aks_update Read more about the command in reference docs
(base) q_li@vm-I-DNA-daas-2:~/Desktop/catalog-web-app$ az aks update --resource-group rg-i-dna-aks --name I-DNA-Cluster --enable-cost-analysis
The command failed with an unexpected error. Here is the traceback:
module 'azure.core.pipeline.policies' has no attribute 'SensitiveHeaderCleanupPolicy'
Traceback (most recent call last):
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/knack/cli.py", line 233, in invoke
cmd_result = self.invocation.execute(args)
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/__init__.py", line 664, in execute
raise ex
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/__init__.py", line 731, in _run_jobs_serially
results.append(self._run_job(expanded_arg, cmd_copy))
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/__init__.py", line 701, in _run_job
result = cmd_copy(params)
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/__init__.py", line 334, in __call__
return self.handler(*args, **kwargs)
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/command_operation.py", line 112, in handler
client = self.client_factory(self.cli_ctx, command_args) if self.client_factory else None
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/command_modules/acs/_client_factory.py", line 27, in cf_managed_clusters
return get_container_service_client(cli_ctx).managed_clusters
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/command_modules/acs/_client_factory.py", line 19, in get_container_service_client
return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_CONTAINERSERVICE, subscription_id=subscription_id)
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/client_factory.py", line 83, in get_mgmt_service_client
client, _ = _get_mgmt_service_client(cli_ctx, client_type, subscription_id=subscription_id,
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/cli/core/commands/client_factory.py", line 254, in _get_mgmt_service_client
client = client_type(credential, subscription_id, **client_kwargs)
File "/home/uenv/q_li/.local/lib/python3.10/site-packages/azure/mgmt/containerservice/_container_service_client.py", line 101, in __init__
policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None,
AttributeError: module 'azure.core.pipeline.policies' has no attribute 'SensitiveHeaderCleanupPolicy'
To check existing issues, please visit: https://github.com/Azure/azure-cli/issues
az aks update --resource-group rg-i-dna-aks --name I-DNA-Cluster --enable-cost-analysis
(OperationNotAllowed) The 'costAnalysis' feature cannot be used unless the cluster SKU.Tier is at least 'Standard'
Code: OperationNotAllowed
Message: The 'costAnalysis' feature cannot be used unless the cluster SKU.Tier is at least 'Standard'``
az aks show --resource-group rg-i-dna-aks --name I-DNA-Cluster --query "sku.tier"
import { Link } from 'react-router-dom';
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function AppMenu() {
metricsList = []
const metricsList: MetricsList[] = [
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' }
]
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' }
]
},
{
subCategory: 'Security',
metrics: [
{ name: 'Vulnerability Scans', provided: true, subCategory: 'Security' },
{ name: 'Intrusion Detection', provided: false, subCategory: 'Security' }
]
}
];
import { Link } from 'react-router-dom';
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function AppMenu() {
const metricsList: MetricsList[] = [
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' }
]
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' }
]
},
{
subCategory: 'Security',
metrics: [
{ name: 'Vulnerability Scans', provided: true, subCategory: 'Security' },
{ name: 'Intrusion Detection', provided: false, subCategory: 'Security' }
]
}
];
return (
<>
<aside className="main-sidebar sidebar-light-primary elevation-2">
{/* Brand Logo */}
<Link to="/" className="brand-link">
<img
src="/logo_fix.02.png"
alt="iQuattro Logo"
className="brand-image"
/>
<img
src="/logo_fix.02_logo.png"
alt="iQuattro Logo"
className="brand-text"
/>
</Link>
{/* Sidebar */}
<div className="sidebar">
{/* Sidebar Menu */}
<nav>
<ul className="nav nav-pills nav-sidebar flex-column">
<li className="nav-header">
<Link to="/new-metrics-list" className="nav-link">
指標一覧
</Link>
</li>
{metricsList?.map((c, idx) => (
<CategoryItem category={c} idx={idx} key={idx} />
))}
</ul>
</nav>
{/* /.sidebar-menu */}
<div className="copyright">Copyright ©NTT DATA Corporation</div>
</div>
{/* /.sidebar */}
</aside>
</>
);
}
export default AppMenu;
import { Link } from 'react-router-dom';
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function AppMenu() {
const metricsList: MetricsList[] = [
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' }
]
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' }
]
}
];
const handleSubmenu = (e: MouseEvent<HTMLAnchorElement>) => {
const $menuItem = $(e.currentTarget as HTMLElement);
const id = $menuItem.data('target');
const $submenu = $(`#${id}`);
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
$submenu.addClass('show');
setTimeout(() => {
$(document).on('click.openSubmenu', (e) => {
if ($(e.target).closest($('.dropdown-menu')).length === 0) {
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
}
});
});
poppers[id].update();
};
function CategoryItem({
category: group,
idx,
}: {
category: MetricsList;
idx: number;
}) {
const defaultCat = defaultCategories.find(
(e) => e.name === group.subCategory,
);
return (
<li className="nav-item">
<a
className="nav-link dropdown"
data-target={`sidebar-cat-${idx + 1}`}
onClick={handleSubmenu}
>
<div className="item-icon">
<i className={`fa ${defaultCat?.icon ?? 'fa-calculator'}`} />
</div>
<div className="item-label">{group.subCategory}</div>
</a>
</li>
);
}
return (
<>
<aside className="main-sidebar sidebar-light-primary elevation-2">
{/* Brand Logo */}
<Link to="/" className="brand-link">
<img
src="/logo_fix.02.png"
alt="iQuattro Logo"
className="brand-image"
/>
<img
src="/logo_fix.02_logo.png"
alt="iQuattro Logo"
className="brand-text"
/>
</Link>
{/* Sidebar */}
<div className="sidebar">
{/* Sidebar Menu */}
<nav>
<ul className="nav nav-pills nav-sidebar flex-column">
<li className="nav-header">
<Link to="/new-metrics-list" className="nav-link">
指標一覧
</Link>
</li>
{metricsList?.map((c, idx) => (
<CategoryItem category={c} idx={idx} key={idx} />
))}
</ul>
</nav>
{/* /.sidebar-menu */}
<div className="copyright">Copyright ©NTT DATA Corporation</div>
</div>
{/* /.sidebar */}
</aside>
</>
);
}
export default AppMenu;
import React from 'react';
import { Link } from 'react-router-dom';
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
const defaultCategories = [
{ name: 'Performance', icon: 'fa-tachometer-alt' },
{ name: 'Availability', icon: 'fa-clock' }
];
const poppers: { [key: string]: any } = {};
function AppMenu() {
const metricsList: MetricsList[] = [
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' }
]
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' }
]
}
];
const handleSubmenu = (e: React.MouseEvent<HTMLAnchorElement>) => {
const $menuItem = $(e.currentTarget as HTMLElement);
const id = $menuItem.data('target');
const $submenu = $(`#${id}`);
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
$submenu.addClass('show');
setTimeout(() => {
$(document).on('click.openSubmenu', (e) => {
if ($(e.target).closest($('.dropdown-menu')).length === 0) {
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
}
});
});
poppers[id].update();
};
function CategoryItem({
category: group,
idx,
}: {
category: MetricsList;
idx: number;
}) {
const defaultCat = defaultCategories.find(
(e) => e.name === group.subCategory,
);
return (
<li className="nav-item">
<a
className="nav-link dropdown"
data-target={`sidebar-cat-${idx + 1}`}
onClick={handleSubmenu}
>
<div className="item-icon">
<i className={`fa ${defaultCat?.icon ?? 'fa-calculator'}`} />
</div>
<div className="item-label">{group.subCategory}</div>
</a>
</li>
);
}
return (
<>
<aside className="main-sidebar sidebar-light-primary elevation-2">
{/* Brand Logo */}
<Link to="/" className="brand-link">
<img
src="/logo_fix.02.png"
alt="iQuattro Logo"
className="brand-image"
/>
<img
src="/logo_fix.02_logo.png"
alt="iQuattro Logo"
className="brand-text"
/>
</Link>
{/* Sidebar */}
<div className="sidebar">
{/* Sidebar Menu */}
<nav>
<ul className="nav nav-pills nav-sidebar flex-column">
<li className="nav-header">
<Link to="/new-metrics-list" className="nav-link">
指標一覧
</Link>
</li>
{metricsList?.map((c, idx) => (
<CategoryItem category={c} idx={idx} key={idx} />
))}
</ul>
</nav>
{/* /.sidebar-menu */}
<div className="copyright">Copyright ©NTT DATA Corporation</div>
</div>
{/* /.sidebar */}
</aside>
</>
);
}
export default AppMenu;
function TopPage() {
const props = {
metricsList,
setMetricsList,
category,
setCategory,
isCategoryTxtDisplayed,
setCategoryTxtDisplayed,
// graph,
// setGraph,
text,
setText,
isAnalyzeBtnDisabled,
setAnalyzeBtnDisabled,
enableCreatingMetrics,
};
return (
<div className="content-wrapper top-page">
<section className="page-cover page-cover-big">
<div className="page-cover-title-frame">
<h1>指標一覧</h1>
</div>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>指標一覧</h1>
<div className='sub'>見たい指標を選択してください</div>
</div>
</section>
</div>
<div className="content-wrapper metrics-list">
<section className="page-cover">
<h1>{title}</h1>
</section>
{/* Content Header (Page header) */}
<section className="content-header">
<div className="content-header-left">
<h1>{title}</h1>
</div>
</section>
{/* Metrics List (Grid) */}
{Spacer({ size: 50 })}
{view(props as any)}
</div>
);
}
const view = (props: MetricsListProps) => {
if (props.metricsList.length) {
return (
<>
<section className="content">
<div className="list-wrapper">
{GridMetricsList(props)}
</div>
</section>
</>
);
}
};
// API List
function GridMetricsList(props: MetricsListProps) {
return (
<>
{props.metricsList.map((metrics: MetricsList) =>
MetricsCard(props, metrics)
)}
</>
);
}
// Metrics Card
function MetricsCard(props: MetricsListProps, metrics: MetricsList) {
return (
<>
<div>
<div className="card card-tertiary card-collapse-metrics">
<div className="card-header">
<div
className="name-font"
style={{
fontSize: `clamp(0.65rem, ${
30 / metrics.subCategory.length
}vw, 1rem)`,
}}
>
{metrics.subCategory}
</div>
</div>
<div className="card-body" id={metrics.subCategory}>
{
<>
{metrics.metrics.map((val) => {
return (
<a
href={`#/metrics-details/${val.name}`}
className="link"
>
<p>
<i
className={`fa fa-circle ${
val.provided
? 'metrics-provide-icon'
: 'metrics-no-provide-icon'
}`}
aria-hidden="true"
/>
{val.name}
</p>
</a>
);
})}
</>
}
</div>
</div>
</div>
</>
);
}
export default TopPage;
ERROR in src/app2/components/pages/topPage.tsx:98:39 TS7006: Parameter 'val' implicitly has an 'any' type.
import React from 'react';
type MetricsListProps = {
metricsList: MetricsList[];
setMetricsList: React.Dispatch<React.SetStateAction<MetricsList[]>>;
category: string;
setCategory: React.Dispatch<React.SetStateAction<string>>;
isCategoryTxtDisplayed: boolean;
setCategoryTxtDisplayed: React.Dispatch<React.SetStateAction<boolean>>;
// graph: any; // Uncomment if needed
// setGraph: any; // Uncomment if needed
text: string;
setText: React.Dispatch<React.SetStateAction<string>>;
isAnalyzeBtnDisabled: boolean;
setAnalyzeBtnDisabled: React.Dispatch<React.SetStateAction<boolean>>;
enableCreatingMetrics: boolean;
};
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function TopPage() {
const metricsList: MetricsList[] = []; // Initialize with actual data
const setMetricsList = () => {}; // Replace with actual setter function
const category = ''; // Replace with actual state
const setCategory = () => {}; // Replace with actual setter function
const isCategoryTxtDisplayed = false; // Replace with actual state
const setCategoryTxtDisplayed = () => {}; // Replace with actual setter function
const text = ''; // Replace with actual state
const setText = () => {}; // Replace with actual setter function
const isAnalyzeBtnDisabled = false; // Replace with actual state
const setAnalyzeBtnDisabled = () => {}; // Replace with actual setter function
const enableCreatingMetrics = false; // Replace with actual state
const props: MetricsListProps = {
metricsList,
setMetricsList,
category,
setCategory,
isCategoryTxtDisplayed,
setCategoryTxtDisplayed,
// graph,
// setGraph,
text,
setText,
isAnalyzeBtnDisabled,
setAnalyzeBtnDisabled,
enableCreatingMetrics,
};
return (
<>
<div className="content-wrapper top-page">
<section className="page-cover page-cover-big">
<div className="page-cover-title-frame">
<h1>指標一覧</h1>
</div>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>指標一覧</h1>
<div className="sub">見たい指標を選択してください</div>
</div>
</section>
</div>
<div className="content-wrapper metrics-list">
<section className="page-cover">
<h1>{props.category}</h1>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>{props.category}</h1>
</div>
</section>
{Spacer({ size: 50 })}
{view(props)}
</div>
</>
);
}
const view = (props: MetricsListProps) => {
if (props.metricsList.length) {
return (
<section className="content">
<div className="list-wrapper">
{GridMetricsList(props)}
</div>
</section>
);
}
return null;
};
const GridMetricsList = (props: MetricsListProps) => {
return (
<>
{props.metricsList.map((metrics: MetricsList) =>
MetricsCard(props, metrics)
)}
</>
);
};
const MetricsCard = (props: MetricsListProps, metrics: MetricsList) => {
return (
<div>
<div className="card card-tertiary card-collapse-metrics">
<div className="card-header">
<div
className="name-font"
style={{
fontSize: `clamp(0.65rem, ${
30 / metrics.subCategory.length
}vw, 1rem)`,
}}
>
{metrics.subCategory}
</div>
</div>
<div className="card-body" id={metrics.subCategory}>
<>
{metrics.metrics.map((val: Metrics) => {
return (
<a href={`#/metrics-details/${val.name}`} className="link" key={val.name}>
<p>
<i
className={`fa fa-circle ${
val.provided
? 'metrics-provide-icon'
: 'metrics-no-provide-icon'
}`}
aria-hidden="true"
/>
{val.name}
</p>
</a>
);
})}
</>
</div>
</div>
</div>
);
};
const Spacer = ({ size }: { size: number }) => (
<div style={{ height: size }} />
);
export default TopPage;
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
type MetricsListProps = {
metricsList: MetricsList[];
setMetricsList: React.Dispatch<React.SetStateAction<MetricsList[]>>;
category: string;
setCategory: React.Dispatch<React.SetStateAction<string>>;
isCategoryTxtDisplayed: boolean;
setCategoryTxtDisplayed: React.Dispatch<React.SetStateAction<boolean>>;
// graph: any; // Uncomment if needed
// setGraph: any; // Uncomment if needed
text: string;
setText: React.Dispatch<React.SetStateAction<string>>;
isAnalyzeBtnDisabled: boolean;
setAnalyzeBtnDisabled: React.Dispatch<React.SetStateAction<boolean>>;
enableCreatingMetrics: boolean;
};
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function TopPage() {
const [metricsList, setMetricsList] = useState<MetricsList[]>([
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' },
],
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' },
],
},
]);
const [category, setCategory] = useState('Performance');
const [isCategoryTxtDisplayed, setCategoryTxtDisplayed] = useState(true);
const [text, setText] = useState('Sample Text');
const [isAnalyzeBtnDisabled, setAnalyzeBtnDisabled] = useState(false);
const [enableCreatingMetrics, setEnableCreatingMetrics] = useState(true);
const props: MetricsListProps = {
metricsList,
setMetricsList,
category,
setCategory,
isCategoryTxtDisplayed,
setCategoryTxtDisplayed,
// graph,
// setGraph,
text,
setText,
isAnalyzeBtnDisabled,
setAnalyzeBtnDisabled,
enableCreatingMetrics,
};
return (
<>
<div className="content-wrapper top-page">
<section className="page-cover page-cover-big">
<div className="page-cover-title-frame">
<h1>指標一覧</h1>
</div>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>指標一覧</h1>
<div className="sub">見たい指標を選択してください</div>
</div>
</section>
</div>
<div className="content-wrapper metrics-list">
<section className="page-cover">
<h1>{category}</h1>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>{category}</h1>
</div>
</section>
{Spacer({ size: 50 })}
{view(props)}
</div>
</>
);
}
const view = (props: MetricsListProps) => {
if (props.metricsList.length) {
return (
<section className="content">
<div className="list-wrapper">
{GridMetricsList(props)}
</div>
</section>
);
}
return null;
};
const GridMetricsList = (props: MetricsListProps) => {
return (
<>
{props.metricsList.map((metrics: MetricsList) =>
MetricsCard(props, metrics)
)}
</>
);
};
const MetricsCard = (props: MetricsListProps, metrics: MetricsList) => {
return (
<div>
<div className="card card-tertiary card-collapse-metrics">
<div className="card-header">
<div
className="name-font"
style={{
fontSize: `clamp(0.65rem, ${
30 / metrics.subCategory.length
}vw, 1rem)`,
}}
>
{metrics.subCategory}
</div>
</div>
<div className="card-body" id={metrics.subCategory}>
<>
{metrics.metrics.map((val: Metrics) => {
return (
<a href={`#/metrics-details/${val.name}`} className="link" key={val.name}>
<p>
<i
className={`fa fa-circle ${
val.provided
? 'metrics-provide-icon'
: 'metrics-no-provide-icon'
}`}
aria-hidden="true"
/>
{val.name}
</p>
</a>
);
})}
</>
</div>
</div>
</div>
);
};
const Spacer = ({ size }: { size: number }) => (
<div style={{ height: size }} />
);
export default TopPage;
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
type MetricsListProps = {
metricsList: MetricsList[];
setMetricsList: React.Dispatch<React.SetStateAction<MetricsList[]>>;
category: string;
setCategory: React.Dispatch<React.SetStateAction<string>>;
isCategoryTxtDisplayed: boolean;
setCategoryTxtDisplayed: React.Dispatch<React.SetStateAction<boolean>>;
// graph: any; // Uncomment if needed
// setGraph: any; // Uncomment if needed
text: string;
setText: React.Dispatch<React.SetStateAction<string>>;
isAnalyzeBtnDisabled: boolean;
setAnalyzeBtnDisabled: React.Dispatch<React.SetStateAction<boolean>>;
enableCreatingMetrics: boolean;
};
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
function TopPage() {
const [metricsList, setMetricsList] = useState<MetricsList[]>([
{
subCategory: 'Performance',
metrics: [
{ name: 'CPU Usage', provided: true, subCategory: 'Performance' },
{ name: 'Memory Usage', provided: false, subCategory: 'Performance' },
{ name: 'Disk I/O', provided: true, subCategory: 'Performance' },
],
},
{
subCategory: 'Availability',
metrics: [
{ name: 'Uptime', provided: true, subCategory: 'Availability' },
{ name: 'Downtime', provided: false, subCategory: 'Availability' },
],
},
]);
const [category, setCategory] = useState('Performance');
const [isCategoryTxtDisplayed, setCategoryTxtDisplayed] = useState(true);
const [text, setText] = useState('Sample Text');
const [isAnalyzeBtnDisabled, setAnalyzeBtnDisabled] = useState(false);
const [enableCreatingMetrics, setEnableCreatingMetrics] = useState(true);
const props: MetricsListProps = {
metricsList,
setMetricsList,
category,
setCategory,
isCategoryTxtDisplayed,
setCategoryTxtDisplayed,
// graph,
// setGraph,
text,
setText,
isAnalyzeBtnDisabled,
setAnalyzeBtnDisabled,
enableCreatingMetrics,
};
return (
<>
<div className="content-wrapper top-page">
<section className="page-cover page-cover-big">
<div className="page-cover-title-frame">
<h1>指標一覧</h1>
</div>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>指標一覧</h1>
<div className='sub'>見たい指標を選択してください</div>
</div>
</section>
</div>
<div className="content-wrapper metrics-list">
<section className="page-cover">
<h1>{category}</h1>
</section>
<section className="content-header">
<div className="content-header-left">
<h1>{category}</h1>
</div>
</section>
{Spacer({ size: 50 })}
{view(props)}
<div className="columns">
<div className="column">
<div className="column-title">Column 1</div>
<div className="column-item">Item 1</div>
<div className="column-item">Item 2</div>
<div className="column-item">Item 3</div>
</div>
<div className="column">
<div className="column-title">Column 2</div>
<div className="column-item">Item 1</div>
<div className="column-item">Item 2</div>
<div className="column-item">Item 3</div>
</div>
</div>
</div>
</>
);
}
const view = (props: MetricsListProps) => {
if (props.metricsList.length) {
return (
<section className="content">
<div className="list-wrapper">
{GridMetricsList(props)}
</div>
</section>
);
}
return null;
};
const GridMetricsList = (props: MetricsListProps) => {
return (
<>
{props.metricsList.map((metrics: MetricsList) =>
MetricsCard(props, metrics)
)}
</>
);
};
const MetricsCard = (props: MetricsListProps, metrics: MetricsList) => {
return (
<div>
<div className="card card-tertiary card-collapse-metrics">
<div className="card-header">
<div
className="name-font"
style={{
fontSize: `clamp(0.65rem, ${
30 / metrics.subCategory.length
}vw, 1rem)`,
}}
>
{metrics.subCategory}
</div>
</div>
<div className="card-body" id={metrics.subCategory}>
<>
{metrics.metrics.map((val: Metrics) => {
return (
<a href={`#/metrics-details/${val.name}`} className="link" key={val.name}>
<p>
<i
className={`fa fa-circle ${
val.provided
? 'metrics-provide-icon'
: 'metrics-no-provide-icon'
}`}
aria-hidden="true"
/>
{val.name}
</p>
</a>
);
})}
</>
</div>
</div>
</div>
);
};
const Spacer = ({ size }: { size: number }) => (
<div style={{ height: size }} />
);
export default TopPage;
.content-wrapper {
padding: 20px;
}
.page-cover-title-frame h1 {
font-size: 2rem;
margin: 0;
padding: 20px;
background-color: black;
color: white;
text-align: center;
}
.content-header-left h1 {
font-size: 1.5rem;
margin-bottom: 10px;
}
.content-header-left .sub {
font-size: 1rem;
color: gray;
}
.columns {
display: flex;
justify-content: space-around;
margin-top: 30px;
}
.column {
width: 45%;
}
.column-title {
background-color: black;
color: white;
padding: 10px;
font-size: 1.2rem;
text-align: center;
}
.column-item {
background-color: white;
color: black;
padding: 10px;
margin: 5px 0;
border: 1px solid black;
text-align: center;
}
.metrics-list .list-wrapper {
/* display: flex; */
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: start;
gap: 15vw;
padding-left: 5vw;
padding-right: 5vw;
}
/* COLLAPSE */
.metrics-list .card-collapse-metrics .card-header {
display: grid;
/* grid-template-columns: 1fr auto; */
cursor: pointer;
position: relative;
/* white-space: nowrap; */
}
.metrics-list .card-collapse-metrics .card-header:after {
content: ' ';
display: block;
transition: transform linear 0.3s;
text-align: center;
font-size: 1rem;
}
.metrics-list .card-collapse-metrics .card-header.collapsed:after {
content: '+';
display: block;
transition: transform linear 0.3s;
font-size: 1rem;
}
.metrics-list .card-header .name-font {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
padding-left: 5%;
white-space: nowrap;
text-align: center;
}
.metrics-list .centering-btn {
text-align: center;
}
.metrics-list .btn-datainsert {
background-color: rgb(235, 235, 235);
}
/* BASE */
.metrics-list .list-wrapper {
/* display: flex; */
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: start;
gap: 5vw;
padding-left: 5vw;
padding-right: 5vw;
}
/* COLLAPSE */
.metrics-list .list {
width: 100%;
}
.metrics-list .list .card {
transition: top, left linear 0.3s;
/* border-radius: 0px 0px 10px 10px; */
}
.metrics-list .list .update ul {
list-style: none;
padding-inline-start: 0;
}
.metrics-list .list .metrics img {
width: 100%;
}
.metrics-list .list .favorities .fav-list {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.metrics-list .list .favorities .card-collapse .card-header {
border-bottom: none;
}
.metrics-list .list .favorities .card-collapse {
border-bottom: 1px solid var(--border-color);
margin-bottom: 0;
}
.metrics-list .list .favorities .fav-list .btn {
padding-left: 10px;
padding-right: 10px;
font-weight: normal;
}
/* List Contents */
/* .metrics-list .list-title {
padding-left: 1vw;
font-weight: bold;
}
.metrics-list .list-contents-grid {
display: grid;
grid-template-columns: 3fr 0.5fr;
align-items: start;
gap: 3vw;
padding-left: 1.5vw;
padding-right: 1.5vw;
}
.metrics-list .col-delete-btn {
text-align: right;
}
.metrics-list .col-delete-btn .fa-times-circle {
color: red;
} */
/* Metrics Detail Modal */
.metrics-list .metrics-dtl-modal-disp-area {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.metrics-list .metrics-dtl-modal-disp-area .metrics-name {
display: flex;
padding-top: 0.5vw;
}
.metrics-list .metrics-dtl-modal-disp-area .sample-data-btn {
text-align: right;
}
.metrics-list .dtl-modal-font-color {
color: #ce638e;
}
.metrics-list .metrics-text {
display: inline-block;
_display: inline;
}
.metrics-list .modal-body .dividing-line {
border: 1px solid #ced4da;
}
.metrics-list .metrics-provide-icon {
color: rgb(0, 255, 135);
}
.metrics-list .metrics-no-provide-icon {
color: red;
}
.metrics-list .link {
color: var(--font-color-main);
text-decoration: underline;
}
.metrics-list .metrics-provide-icon {
color: rgb(0, 255, 135);
}
{val.name}
{!val.provided && (
<i className="fa fa-exclamation metrics-no-provide-icon" aria-hidden="true" />
)}``
.card-tertiary .card-body{
background-color: var(--content-bg-color);
}
<div className="card-body" id={metrics.subCategory}>
<>
{metrics.metrics.map((val: Metrics) => {
return (
<a href={`#/metrics-details/${val.name}`} className="link" key={val.name}>
<p>
{!val.alert && (
<i
className="fa fa-exclamation metrics-no-provide-icon"
aria-hidden="true"
style={{marginLeft:'10px'}}/>)}
{val.name}
</p>
</a>
);
})}
</>
.card-tertiary .card-body {
background-color: white; /* 设置背景颜色为白色 */
color: black; /* 设置文字颜色为黑色 */
border-radius: 10px; /* 设置圆角 */
padding: 20px; /* 设置内边距 */
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); /* 设置阴影效果 */
}
.metrics-item {
background-color: white;
color: black;
padding: 10px;
margin: 5px 0;
border: 1px solid black;
border-radius: 10px; /* 设置圆角 */
text-align: center;
display: flex;
justify-content: space-between; /* 在两端之间保持间距 */
align-items: center; /* 垂直方向居中对齐 */
}
.metrics-item-container {
display: flex;
align-items: center; /* 垂直方向居中对齐 */
margin: 5px 0; /* 调整项目之间的间距 */
}
.metrics-item::after {
content: ''; /* 添加一个空白占位符 */
display: inline-block;
width: 2rem; /* 设置与感叹号相同的宽度 */
height: 2rem; /* 设置与感叹号相同的高度 */
visibility: hidden; /* 确保占位符不可见 */
}
import * as Popper from '@popperjs/core';
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
type MetricsList = {
subCategory: string;
metrics: Metrics[];
};
type Metrics = {
name: string;
provided: boolean;
subCategory: string;
};
const defaultCategories = [
{ name: 'Performance', icon: 'fa-tachometer-alt' },
{ name: 'Availability', icon: 'fa-clock' }
];
const poppers: { [key: string]: Popper.Instance } = {};
function AppMenu() {
const metricsList: MetricsList[] = [
{
subCategory: '経営指標',
metrics: [
{ name: '売上', provided: true, subCategory: '経営指標' },
{ name: '売上高総利益', provided: true, subCategory: '経営指標' },
{ name: '営業利益', provided: true, subCategory: '経営指標' },
{ name: '売上高総利益率', provided: true, subCategory: '経営指標' },
{ name: '売上高営業利益率', provided: true, subCategory: '経営指標' },
{ name: 'EBITDA', provided: true, subCategory: '経営指標' },
{ name: '当座比率', provided: true, subCategory: '経営指標' },
{ name: '運転資本', provided: true, subCategory: '経営指標' },
{ name: '損益分岐点比率', provided: true, subCategory: '経営指標' },
{ name: '在庫回転率', provided: true, subCategory: '経営指標' },
{ name: '労働生産性①従業員あたり', provided: true, subCategory: '経営指標' },
{ name: '労働生産性②労働時間あたり', provided: true, subCategory: '経営指標' },
{ name: '資金繰り表', provided: true, subCategory: '経営指標' }
]
},
{
subCategory: '管理指標',
metrics: [
{ name: '総合設備効率(OEE)', provided: true, subCategory: '管理指標' },
{ name: '設備稼働率', provided: false, subCategory: '管理指標' },
{ name: '工程別生産性', provided: false, subCategory: '管理指標' },
{ name: '歩留まり率', provided: false, subCategory: '管理指標' },
{ name: '良品率', provided: false, subCategory: '管理指標' },
{ name: '直行率生', provided: false, subCategory: '管理指標' },
{ name: '生産実績', provided: false, subCategory: '管理指標' },
{ name: '在庫数', provided: false, subCategory: '管理指標' },
{ name: '工程管理', provided: false, subCategory: '管理指標' },
{ name: 'マーケット情報', provided: false, subCategory: '管理指標' }
]
}
];
useEffect(() => {
$('.dropdown').each((idx, menuItem) => {
const $menuItem = $(menuItem);
const id = $menuItem.data('target');
const $submenu = $(`#${id}`);
const popper = Popper.createPopper(menuItem, $submenu[0], {
placement: 'right-start',
strategy: 'fixed',
modifiers: [
{
name: 'offset',
options: {
offset: [-1, 0],
},
},
],
});
poppers[id] = popper;
});
$('.dropdown-menu .dropdown-item').on('click', () => {
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
});
}, [metricsList]);
const handleSubmenu = (e: React.MouseEvent<HTMLAnchorElement>) => {
const $menuItem = $(e.currentTarget as HTMLElement);
const id = $menuItem.data('target');
const $submenu = $(`#${id}`);
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
$submenu.addClass('show');
setTimeout(() => {
$(document).on('click.openSubmenu', (e) => {
if ($(e.target).closest($('.dropdown-menu')).length === 0) {
$('.dropdown-menu').removeClass('show');
$(document).off('click.openSubmenu');
}
});
});
poppers[id].update();
};
function CategoryItem({
category: group,
idx,
}: {
category: MetricsList;
idx: number;
}) {
const defaultCat = defaultCategories.find(
(e) => e.name === group.subCategory,
);
return (
<li className="nav-item">
<a
className="nav-link dropdown"
data-target={`sidebar-cat-${idx + 1}`}
onClick={handleSubmenu}
>
<div className="item-icon">
<i className={`fa ${defaultCat?.icon ?? 'fa-calculator'}`} />
</div>
<div className="item-label">{group.subCategory}</div>
</a>
</li>
);
}
return (
<>
<aside className="main-sidebar sidebar-light-primary elevation-2">
{/* Brand Logo */}
<Link to="/" className="brand-link">
<img
src="/logo_fix.02.png"
alt="iQuattro Logo"
className="brand-image"
/>
<img
src="/logo_fix.02_logo.png"
alt="iQuattro Logo"
className="brand-text"
/>
</Link>
{/* Sidebar */}
<div className="sidebar">
{/* Sidebar Menu */}
<nav>
<ul className="nav nav-pills nav-sidebar flex-column">
<li className="nav-header">
<Link to="/" className="nav-link">
指標一覧
</Link>
</li>
{metricsList?.map((c, idx) => (
<CategoryItem category={c} idx={idx} key={idx} />
))}
</ul>
</nav>
{/* /.sidebar-menu */}
<div className="copyright">Copyright ©NTT DATA Corporation</div>
</div>
{/* /.sidebar */}
</aside>
<div className="sidebar-dropdowns">
{metricsList?.map((g, idx) => (
<ul className="dropdown-menu" id={`sidebar-cat-${idx + 1}`} key={idx}>
{g.metrics.map((m) => (
<li className="dropdown-item" key={m.name}>
<Link to={`/metrics-details/${m.name}`} className="nav-link">
{m.name}
</Link>
</li>
))}
</ul>
))}
</div>
</>
);
}
export default AppMenu;
<i className={
fa ${val.icon} metrics-icon} aria-hidden="true" />
<i className={fa ${val.icon} metrics-icon
} aria-hidden="true" />
<i className={
fa ${val.icon} metrics-icon} aria-hidden="true" />
<i className={
fa ${val.icon} metrics-icon} aria-hidden="true" />
.alert-box {
background-color: white;
color: black;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
margin: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.alert-box span {
flex-grow: 1;
}
.close-btn {
background-color: transparent;
border: none;
color: red;
cursor: pointer;
font-size: 1rem;
padding: 5px;
margin-left: 10px;
}
import React, { useState } from 'react';
import AlertBox from './AlertBox'; // 引入警告弹窗组件
function AppMenu() {
const [showAlert, setShowAlert] = useState(true); // 控制警告弹窗的显示
return (
<>
{/* 其他代码 */}
{showAlert && (
<AlertBox
message="これは警告メッセージです"
onClose={() => setShowAlert(false)}
/>
)}
</>
);
}
export default AppMenu;
import React from 'react';
const AlertBox = ({ message, onClose }: { message: string; onClose: () => void }) => {
return (
<div className="alert-box">
<span>{message}</span>
<button className="close-btn" onClick={onClose}>非表示</button>
</div>
);
};
export default AlertBox;
import { useState } from "react";
function EmptyPage() {
// function get() {
const test = '資金繰り表';
// return arr.map((str) => {
// SampleDataModal(str);
// });
// }
const [showAlert, setShowAlert] = useState(true); // 控制警告弹窗的显示
const AlertBox = ({ message, onClose }: { message: string; onClose: () => void }) => {
return (
<div className="alert-box">
<span>{message}</span>
<button className="close-btn" onClick={onClose}>非表示</button>
</div>
);
};
return (
<div className="content-wrapper metrics-details">
<section className="page-cover">
<div className="page-cover-title-frame">
<h1>{test}</h1>
</div>
</section>
{/* Content Header (Page header) */}
<section className="content-header">
<div className="content-header-left">
<div>期中に資金がマイナスとなる期間があります</div>
</div>
</section>
</div>
);
}
export default EmptyPage;
import { useState } from "react";
function EmptyPage() {
const test = '資金繰り表';
const [showAlert, setShowAlert] = useState(true); // 控制警告弹窗的显示
const AlertBox = ({ message, onClose }: { message: string; onClose: () => void }) => {
return (
<div className="alert-box">
<span>{message}</span>
<button className="close-btn" onClick={onClose}>非表示</button>
</div>
);
};
return (
<div className="content-wrapper metrics-details">
<section className="page-cover">
<div className="page-cover-title-frame">
<h1>{test}</h1>
</div>
</section>
{/* Content Header (Page header) */}
<section className="content-header">
<div className="content-header-left">
<div>期中に資金がマイナスとなる期間があります</div>
</div>
</section>
{/* 警告弹窗 */}
{showAlert && (
<AlertBox
message="これは警告メッセージです"
onClose={() => setShowAlert(false)}
/>
)}
</div>
);
}
export default EmptyPage;
let cpu_rate_per_core_hour = 0.048; // 1 vCPUあたりの料金(USD/時間) let mem_rate_per_gb_hour = 0.012; // 1 GiB RAMあたりの料金(USD/時間)
// 各名前空間のCPU使用量の料金計算 let cpu_cost = KubePodInventory | summarize AvgCPU=avg(TotalCpuUsageNanoCores) by Namespace | extend CPUHours = AvgCPU (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / 1e9 | extend CPUCost = CPUHours cpu_rate_per_core_hour;
// 各名前空間のメモリ使用量の料金計算 let mem_cost = KubePodInventory | summarize AvgMemory=avg(TotalMemoryUsageBytes) by Namespace | extend MemoryHours = AvgMemory (datetime_diff('hour', max(TimeGenerated), min(TimeGenerated))) / (1024 1024 1024) | extend MemoryCost = MemoryHours mem_rate_per_gb_hour;
// CPUとメモリの料金を統合 cpu_cost | join kind=inner (mem_cost) on Namespace | project Namespace, CPUCost, MemoryCost, TotalCost = CPUCost + MemoryCost