يمكنك دمج لوحات تحكم Sprucely.io التفاعلية في موقعك الإلكتروني أو تطبيق الويب الخاصّين بك بثلاث طرق: بتضمينها عبر عنصر iframe قياسي بلغة HTML، أو بعرضها مباشرةً باستخدام بيئة تشغيل JavaScript المستقلة، أو بتركيب مكوّنات React المستقلة. يُعَدّ iframe الطريقة الأسرع في الإعداد؛ أما بيئات التشغيل المستقلة فترسم لوحات التحكم مباشرةً داخل صفحتك وتتيح لك ضخّ بيانات جديدة أثناء التشغيل. أما بنية JSON التي تقرأها بيئات التشغيل المستقلة - لوحات التحكم والمخططات ومجموعات البيانات - فموثَّقة في مرجع تنسيق البيانات. للأتمتة المدعومة بالذكاء الاصطناعي للوحات التحكم، راجع قسم واجهات MCP API.
تضمين لوحات التحكم في HTML
أبسط طريقة للتكامل هي استخدام عنصر iframe القياسي بلغة HTML، وهي تعمل على أي موقع إلكتروني، بل حتى على صفحات HTML محلية. يجب أن تكون لوحة التحكم مُشارَكة، سواء في السحابة أو محلياً، حتى يتم تحميلها بنجاح. يُرجى ملاحظة أن لوحات التحكم المحلية لا تُحمَّل إلا عندما يكون العميل الذي يصل إليها ضمن الشبكة المؤسسية نفسها.
التعليمات:
1) استخرج رابط تضمين لوحة التحكم - في صفحة لوحات التحكم، تأكَّد من أن لوحة التحكم الخاصة بك مُشارَكة، ثم انقر على أيقونة الخاصة بلوحة التحكم هذه. ستظهر لافتة منبثقة خضراء تُعلمك بأن الرابط قد نُسخ إلى الحافظة. ستستخدم هذا الرابط لاستبدال محتوى الخاصية src في عنصر iframe بلغة HTML أدناه.
2) ضمّن لوحة التحكم بحجم ثابت
<html>
<head>
<title>Sprucely.io Dashboard</title>
</head>
<body>
<h1>Sprucely.io Dashboard</h1>
<iframe src="https://www.sprucely.io/service/dashboards/embed/[userId]/[dashboardId]/"
allow="clipboard-write"
style="height: 500px; width: 700px;"
title="Sprucely.io Dashboard"></iframe>
</body>
</html>(أو) ضمّن لوحة التحكم بعرض ديناميكي - يُعيد تحجيم لوحة التحكم تلقائياً استناداً إلى عرض المستند الأصل
يمكنك استخدام معلمة النمط aspect-ratio لإعادة احتساب الارتفاع تلقائياً استناداً إلى العرض.
<html>
<head>
<title>Sprucely.io Dashboard</title>
</head>
<body>
<h1>Sprucely.io Dashboard</h1>
<iframe src="https://www.sprucely.io/service/dashboards/embed/[userId]/[dashboardId]/"
allow="clipboard-write"
scrolling="no"
style="width: 100%; aspect-ratio: 1.5; border: none;"
title="Sprucely.io Dashboard"></iframe>
</body>
</html>3) خيارات تضمين مفيدة أخرى
يمكنك إضافة تعديلات نمط مخصَّصة إلى كتلة style الخاصة بعنصر iframe، لتخصيص مظهر الإطار وأسلوبه. تتبع هذه المعلمات إرشادات HTML وCSS القياسية. يضيف المثال أدناه حدوداً رمادية حول لوحة التحكم:
<html>
<head>
<title>Sprucely.io Dashboard</title>
</head>
<body>
<h1>Sprucely.io Dashboard</h1>
<iframe src="https://www.sprucely.io/service/dashboards/embed/[userId]/[dashboardId]/"
allow="clipboard-write"
style="height: 100%; width: 100%; border: 2px solid grey;"
title="Sprucely.io Dashboard"></iframe>
</body>
</html>التضمين ببيئة تشغيل JavaScript المستقلة
تعرض بيئة التشغيل المستقلة لوحات التحكم مباشرةً داخل صفحتك - دون iframe. تُحمَّل بياناتك في قاعدة بيانات داخل المتصفح وتُرسم كمخططات تفاعلية بالكامل؛ ولا تتواصل بيئة التشغيل مع Sprucely.io إلا للتحقق من رمز الوصول الخاص بك.
التعليمات:
1) أنشئ رمز وصول - في قسم رموز الوصول ضمن ملفك الشخصي، أنشئ رمز وصول للمصدر الذي تُقدَّم منه صفحاتك (على سبيل المثال https://www.yourdomain.com). تتحقق بيئة التشغيل من تطابق مصدر الصفحة المُضمِّنة مع الرمز قبل العرض.
2) حمِّل بيئة التشغيل واعرض لوحة تحكم - أضف نص بيئة التشغيل البرمجي (script) إلى صفحتك، ثم اتصل بقاعدة البيانات داخل المتصفح مرة واحدة باستخدام sprucely_db، ثم اعرض كل لوحة تحكم باستخدام sprucely_create. تربط الصفحة الكاملة أدناه أيضاً زراً يُضيف مزيداً من الصفوف:
<html>
<head>
<title>Orders Dashboard</title>
</head>
<body>
<div id="database"></div>
<div id="orders_dashboard"></div>
<button onclick="addRows()">Add rows</button>
<script src="https://www.sprucely.io/cross-origin/sprucely-runtime.min.js"></script>
<script>
const data = {
name: "Orders",
headers: ["region", "amount", "items"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["North", 120.50, 2],
["South", 89.95, 1],
["North", 432.00, 5],
["South", 74.50, 1]
]
};
const dashboard = {
config: {
type: "dashboard",
style: {
widget: {
color: "#667FFF",
backgroundColor: "#0C0B29",
primaryColor: "#01EEAE",
primaryColorSubtle: "#C70584",
secondaryColor: "#2C2B49"
}
}
},
data: {
type: "dash",
children: [
{
type: "dash_stacker_hor",
children: [
{ type: "dash_chart", datasetId: "Orders", x: "region", chartType: "bar", dataFunction: "count" },
{ type: "dash_chart", datasetId: "Orders", x: "amount", y: "items", chartType: "hexbin", dataFunction: "count" }
]
}
]
}
};
sprucely_db({
id: "database",
host: "https://www.yourdomain.com",
accessToken: "YOUR_ACCESS_TOKEN"
});
sprucely_create({ id: "orders_dashboard", dashboard, data });
function addRows() {
sprucely_add({
name: "Orders",
headers: ["region", "amount", "items"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["East", 310.40, 3],
["West", 129.95, 1]
]
});
}
</script>
</body>
</html>3) أضِف بيانات أثناء التشغيل - استدعِ sprucely_add مع صفوف إضافية في أي وقت. تُحدَّث تلقائياً كل لوحة تحكم تستخدم مجموعة البيانات هذه:
sprucely_add({
name: "Orders",
headers: ["region", "amount", "items"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["East", 310.40, 3],
["West", 129.95, 1]
]
});مرجع الدوال
sprucely_db({ id, host, accessToken })- يتصل بقاعدة البيانات داخل المتصفح ويتحقق من رمز الوصول الخاص بك مقابل مصدر الصفحة. يعرض لافتة حالة داخل العنصر المحدَّد بواسطة id. استدعِها مرة واحدة لكل صفحة، قبل إنشاء لوحات التحكم.sprucely_create({ id, dashboard, data })- يعرض لوحة تحكم واحدة داخل العنصر المحدَّد بواسطة id. تحدِّد المعلمة dashboard التخطيط والتنسيق؛ بينما توفِّر data مجموعة البيانات باسمها وأسماء أعمدتها وأنواع أعمدتها (VARCHAR،INTEGER،FLOATأوTIMESTAMP) وصفوفها - راجع مرجع تنسيق البيانات.sprucely_add(data)- يُضيف صفوفاً إلى مجموعة البيانات التي يطابق اسمها مجموعة بيانات محمَّلة بالفعل، ثم يُحدِّث كل لوحات التحكم التي تستخدمها.
التضمين بمكوّنات React المستقلة
إذا كان موقعك مبنياً بلغة React، يمكنك عرض لوحات التحكم كمكوّنات بدلاً من تحميل النص البرمجي يدوياً. تستخدم هذه المكوّنات رموز الوصول نفسها، وتعريفات لوحات التحكم، وتنسيق مجموعة البيانات ذاته المُستخدَم في بيئة تشغيل JavaScript المستقلة.
التعليمات:
1) أنشئ رمز وصول - كما هي الحال مع JavaScript المستقل، أنشئ رمز وصول لمصدر موقعك في قسم رموز الوصول ضمن ملفك الشخصي.
2) اعرض مكوّنات لوحة التحكم - احصل على بيئة التشغيل من https://www.sprucely.io/cross-origin/sprucely-runtime.min.cjs.js وضعها في مشروعك. ركِّب مكوّن Sprucely.Database واحداً لكل صفحة، ومكوّن Sprucely.Dashboard واحداً لكل لوحة تحكم. تعرض لوحات التحكم مؤشر تحميل إلى أن تتحقق قاعدة البيانات من رمز الوصول، ثم تُعرَض. يعرض التطبيق الكامل أدناه لوحتي تحكم من مجموعتي بيانات منفصلتين، ويُضيف صفوفاً جديدة إلى اللوحة الأولى بعد خمس ثوانٍ:
// Get https://www.sprucely.io/cross-origin/sprucely-runtime.min.cjs.js
// and place it in your project, next to this file.
import React, { useEffect } from "react";
import { createRoot } from "react-dom/client";
import Sprucely, { sprucely_add } from "./sprucely-runtime.min.cjs.js";
const style = {
widget: {
color: "#667FFF",
backgroundColor: "#0C0B29",
primaryColor: "#01EEAE",
primaryColorSubtle: "#C70584",
secondaryColor: "#2C2B49"
}
};
const orders = {
name: "Orders",
headers: ["region", "amount", "items"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["North", 120.50, 2],
["South", 89.95, 1],
["North", 432.00, 5],
["South", 74.50, 1]
]
};
const returns = {
name: "Returns",
headers: ["reason", "amount", "days"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["Damaged", 45.00, 3],
["Late", 12.50, 8],
["Changed", 99.90, 2]
]
};
const moreOrders = {
name: "Orders",
headers: ["region", "amount", "items"],
types: ["VARCHAR", "FLOAT", "INTEGER"],
entries: [
["East", 310.40, 3],
["West", 129.95, 1]
]
};
const ordersDashboard = {
config: { type: "dashboard", style },
data: {
type: "dash",
children: [
{
type: "dash_stacker_hor",
children: [
{ type: "dash_chart", datasetId: "Orders", x: "region", chartType: "bar", dataFunction: "count" },
{ type: "dash_chart", datasetId: "Orders", x: "amount", y: "items", chartType: "hexbin", dataFunction: "count" }
]
}
]
}
};
const returnsDashboard = {
config: { type: "dashboard", style },
data: {
type: "dash",
children: [
{
type: "dash_stacker_hor",
children: [
{ type: "dash_chart", datasetId: "Returns", x: "amount", y: "days", d: "amount", r: "days", chartType: "dot", dataFunction: "average" }
]
}
]
}
};
const App = () => {
useEffect(() => {
const timer = setTimeout(() => { sprucely_add(moreOrders); }, 5000);
return () => clearTimeout(timer);
}, []);
return (
<>
<Sprucely.Database host="https://www.yourdomain.com" accessToken="YOUR_ACCESS_TOKEN" />
<Sprucely.Dashboard id="orders_dashboard" dashboard={ordersDashboard} data={orders} />
<Sprucely.Dashboard id="returns_dashboard" dashboard={returnsDashboard} data={returns} />
</>
);
};
createRoot(document.getElementById("root")).render(<App />);تقديم رموز قصيرة الأمد
رمز الوصول الذي تُنشئه أعلاه طويل الأمد، ويُقصَد به أن يبقى سرّاً على مستوى الخادم. فإذا كان الخادم الخلفي الخاص بك هو من يقدِّم صفحات التضمين - بدلاً من صفحة لا تملك خادماً خلفياً خاصاً بها - فلست بحاجة إلى وضع ذلك الرمز طويل الأمد في الصفحة إطلاقاً؛ إذ يمكن لخادمك الخلفي استبداله، من خادم إلى خادم، برمز عرض قصير الأمد (مدته 15 دقيقة) مباشرةً قبل تقديم كل صفحة، بحيث لا يصل إلى المتصفح سوى رمز العرض هذا. أما رمز العرض الذي يستخرجه الزائر من الصفحة فلا يُجدي نفعاً إلا لدقائق معدودة، لا إلى أجل غير مسمى.
التعليمات:
1) استبدل رمز الوصول الخاص بك برمز عرض - من خادمك الخلفي، استدعِ POST https://www.sprucely.io/api/auth/render_token مع رمز الوصول الخاص بك بصفته بيانات اعتماد Bearer. تحمل الاستجابة الرمز الجديد، والمضيف المرتبط به، ومدة صلاحيته بالثواني:
// On your server, immediately before serving each embedding page:
const response = await fetch("https://www.sprucely.io/api/auth/render_token", {
method: "POST",
headers: { Authorization: "Bearer " + process.env.SPRUCELY_ACCESS_TOKEN }
});
const { token, expires_in } = await response.json(); // expires_in: 900 (15 minutes)
// Send only the render token to the browser - never the long-lived access
// token itself:
res.send(`
<script src="https://www.sprucely.io/cross-origin/sprucely-runtime.min.js"></script>
<script>
sprucely_db({
id: "database",
host: "https://www.yourdomain.com",
accessToken: "${token}"
});
</script>
`);2) قدِّم رمز العرض إلى المتصفح - استخدمه تماماً كرمز الوصول عند استدعاء sprucely_db أو تركيب Sprucely.Database. كرِّر عملية الاستبدال قبل تقديم كل صفحة (أو وفق مؤقّت إذا كنت تخزِّن الصفحة المُصيَّرة مؤقتاً)، حتى لا يتلقى المتصفح أبداً رمزاً صالحاً لأكثر من 15 دقيقة.
مرجع الدوال
POST /api/auth/render_token- يستبدل رمز وصول صالحاً، يُرسَل بصيغةAuthorization: Bearer <token>، برمز عرض. يعيد{ token, host, expires_in }مع تثبيتexpires_inعند 900 ثانية. لا يمكن استبدال رمز عرض برمز عرض آخر - فرمز الوصول طويل الأمد وحده يمكنه طلب رمز عرض.
إعدادات الأمان
إذا كان موقعك يفرض سياسة أمان المحتوى (CSP)، فإن تكاملَي JavaScript وReact المستقلَّين أعلاه يحتاجان إلى السماح ببضعة مصادر قبل أن تتمكن لوحات التحكم من التحميل - إذ تُحمِّل بيئة التشغيل نصها البرمجي من Sprucely.io، وتفتح قاعدة بيانات داخل المتصفح مبنية على WebAssembly، وتتحقق من رمز الوصول الخاص بك مقابل واجهة API الخاصة بنا، ويحتاج كل من هذه العناصر إلى إذن CSP صريح. إذا كان موقعك لا يستخدم CSP، يمكنك تخطي هذا القسم.
أضِف المصادر التالية إلى سياستك الحالية - فهذه توجيهات يجب دمجها ضمنها، لا سياسة كاملة تحل محل ما لديك بالفعل:
script-src 'self' https://www.sprucely.io 'wasm-unsafe-eval';
connect-src 'self' https://www.sprucely.io;
worker-src 'self' blob: https://www.sprucely.io;الغرض من كل توجيه:
script-src- يُحمِّلhttps://www.sprucely.ioالنص البرمجي لبيئة التشغيل. ويلزم'wasm-unsafe-eval'لتجميع قاعدة البيانات داخل المتصفح وتشغيلها، وهي مبنية على WebAssembly.connect-src- يُتَّصَل بـhttps://www.sprucely.ioللتحقق من رمز الوصول الخاص بك ولتحميل ملفات WebAssembly وملفات worker الخاصة بقاعدة البيانات.worker-src- تُشغِّل قاعدة البيانات داخل المتصفح استعلاماتها على مسار خلفي، يُنشأ من عنوان URL من نوعblob:.
لا يحتاج أي مما سبق إلى 'unsafe-inline' - فبيئة تشغيل Sprucely نفسها لا تحتاج إليه أبداً. أما إذا احتفظت بتعريفات لوحة التحكم ومجموعة البيانات الخاصة بك داخل وسم <script> مضمَّن، كما في مثال JavaScript المستقل أعلاه، أو كانت صفحتك تستخدم أنماطاً مضمَّنة، فأضِف 'unsafe-inline' إلى script-src أو style-src، أو فكِّر في استخدام CSP nonces.