


السمعة:
- إنضم15 سبتمبر 2023
- المشاركات 30
- الحلول 1
- مستوى التفاعل 44
- النقاط 18
السلام عليكم و رحمة الله و بركاته
اليوم سنجرب صنع واجهة برمجة التطبيقات (API) لموقع NOTION
ماهو واجهة برجمة التطبيقات أو API :
إن API ببساطة هو مجموعة من البرمجيات التى تسمج لتطبيقين مختلفين التواصل والتفاعل مع بعضهم البعض. عند استخدام API، يمكن للمطورين استخدام وظائف محددة أو الحصول على بيانات محددة من تطبيق آخر أو خدمة ويب دون الحاجة إلى معرفة كامل التفاصيل عن كيفية عمل هذا التطبيق أو الخدمة. وبالتالي، يمكن للمطورين بناء تطبيقات جديدة تعتمد على البيانات أو الخدمات التي توفرها API بدلاً من إعادة بناء كل هذه الوظائف من الصفر (التعريف من موقع </مطور>)
فالـ api بكل بساطة هو مكان أرسل فيه طلب لبيانات فيرسلها لي إذا كان موجودة قد تكون ببصيغة json (أكثر شهرة) أو xml أو yaml (أقل شهرة)
لماذا أريد صنع ِAPI لهذا الموقع ؟
- أكتب ملاحظات شخصية يومية
- أشفر الملاحظات الشخصية قبل ما أحطها بالموقع
المشروع سيكون بلغة typescript مع Next framework
لذلك ستحتاج إلى:
1. node package manager
2. Operating systems: macOS, Windows (including WSL), or Linux
3. text editor like vsc
بسم الله نبدأ...
أول شيء سنحتاجه إنشاء مشروع next-js وده راح يكون باستخدام الأمر التالي :
كود:
npx create-next-app@latest
ثم سيسألنا أسئلة غريبة كالتالي:
كود:
What is your project named? notion-api
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like your code inside a `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to use Turbopack for `next dev`? No / Yes
Would you like to customize the import alias (`@/*` by default)? No / Yes







لذلك سأجيب بـ لا
ال bundler هو أداة التي تترجم ملفات المشروع و أكواد ال css ,js الخ إلى موقع أو تطبيق , و أشهرهم كما قلنا هو ال webpack
الثامن سيكون غريبًا لو ترجمته لذلك سنتطرق إليه في وسط الشرح بإذن الله
في الأخير سيكون لدينا ملف اسمه notion-api و ستكون داخله ملفات المشروع.
ثاني شيء سيكون رحلة البحث عن notion api سيكون لموقع notion api's و نحن سننستخدمهم
هذا هو الموقع: devs.notion
هذا سيكون صديقنا طوال المشروع
أول شيء يطلب منا هو internal integration
internal integration هو الذي سيتيح لنا التواصل مع صفاحتنا بالموقع فلإتمام هذه العملية سنطلب توكن من الموقع و سيتيح لنا من خلاله التواصل مع الموقع.
سندخل لهذه الصفحة: notion.integration
تم سنضغط new intgration


ندخل لـ manage settings
نقوم بالرجوع للمشروع ننشئ ملف نسميه .env, ونكتب فيه اسم env var و نقوم بلصق توكن ال intgration
ندخل على موقع notion تم على صفحة التي نريد صنع الواجهة لها تم كما هو موضح في الصورة:
هذا سيتيح لأي شخص لديه التوكن حق integration أن يعدل على الصفحة
سندخل على وثائق الموقع بذات في retrieve a database:
retrieve.database.notion
نقوم بالرجوع على مشروعنا ونكتب الأمر التالي:
كود:
npm run dev
بيظهر لنا أن المشروع بدأ في الينك الآتي على المنفذ 3000 نقوم بدخول إليه:
تظهر لنا هذه الواجهة يمكنك إلقاء النظرة عليها لأنها تحتوي على روابط قد تكون مفيدة لمن يريد تعلم هذا الإطار
نرجع لمحرر الأكواد ونقوم بالدخول على مجلد app تم ملف page.tsx و نقوم بمسح كل شيء:
أول شيء نكتبه:
نعيد فتح المتصفح على المنفذ 3000 فسنرى أن:
داخل مجلد app نفتح مجلد نسميه lib ننشئ ملف نسميه action.ts, و نقوم بلصق الكود الذي أخدنه من وثائق موقع notion
نرجع لملف .env, ننشئ env var نسميه databaseID و نعطيه قيمة معرف الصفحة التي نسخها من رابط الموقع.
تم بنجاح...
نرجع لملف app/lib/actions.ts, نقوم بتغيرات بسيطة كما هي موضحة بالصور:
نشرح المصطلحات التي تم تستطيرها بالأصفر:
[COLOR=rgb(247, 218, 100)]require('@notionhq/client');[/COLOR]
هذا يعني أنه سنحتاج إلى مكتبة اسمها @notionhq/client لذلك سنقوم بتنزيلها باستعمال الأمر التالي:
كود:
npm install @notionhq/client



و الآن ننشئ مجلد نسميه database (يمكنك تغير الاسم) داخله ننشئ ملف نسميه page.tsx و في هذه الحالة لا يجب تغير اسم page.tsx لأنه سيصبح غير قابل للتوجيه أو زيارة و هذه من قواعد إطار Next-js
داخل ملف: app/database/page.tsx
نقوم بإنشاء عنصر نسميه أي اسم أنا أسميته Notion و نقوم بإستدعاء الدالة RetriveDatabase في الملف
ماذا تعني @ التي قمنا بإحاظتها بمربع أحمر ترمز للمجلد الرئيسي في المشروع و هذا يرجعنا للسؤال الثامن حيث ان سؤال كان ماذا تريد أن يكون ترميز المجلد الرئيسي ونحن قررنا أن يكون بإعدادت الإفتراضية لهاذا الهيكل و هو @
نفتح المتصفح على localhost:3000/database
تم نأخد نظرة على موجه الأوامر في محرر الكود الخاص بنا فنجد
لو تقوم بتدقيق في هذه البيانات ستجد أنها معلومات على databasenotion
داخلها نجد properties و هي خواص ال database أو يمكنك تسميتها أعمدة ال database
كل خاصية لها إسم و لها id لذلك سننسخ الid و نضعها قي ملف .env
في @/app/lib/actions.ts
نكتب
طبعا ستتسألون من أين أتيت بالكود هذا
طبعا بمساعدة notion api doucemnets
مثل ما قلت لكم سيكون صديقكم طوال رحلة برمجة هذا المشروع
تجدونه في هذا المثال كيف يجب أن يكون الكود
create.page.notion
هذا مثال عن كيف يجب أن تكون الخصائص مكتوبة لنوع العنوان (title)
JSON:
{
"properties": {
"Title": {
"id": "title",
"type": "title",
"title": [
{
"type": "text",
"text": {
"content": "A better title for the page",
"link": null
},
"annotations": {
"bold": false,
"italic": false,
"strikethrough": false,
"underline": false,
"code": false,
"color": "default"
},
"plain_text": "This is also not done",
"href": null
}
]
}
}
}
نقوم بمنادة CreateApage function من داخل العنصر الذي أنشأنه داخل مجلد ال database
ندخل من المتصفح على الرابط localhost:3000/database
و نرجع لموقع notion و surprise
لنقم بتمرير ال tags
مثال عن ال كيفية تمرير ال tags
لكن سنقوم بتغيير من شكله ليصبح بإستطاعتنا غدخال ال tags كا مدخل للدالة
بتفكير منطقي يجب علينا إدخال مصفوفة تحتوي على ال tags
تم نقوم ب دوران حول هذه المصفوفة لإرسال هذه tags
كما هو موضح بصورة
map loop
ماهو الفرق بينها و بين for loop
map loop :
تستخدم في غالب الأححيان لتعديل مصفوفة وإرجاع مصفوفة جديدة تحتوي القيم الجديدة
مثلا محاولة تحويل مصفوفة تحتوي على أرقام إلى مصفوفة تحتوي على مربع تلك الأرقام
JavaScript:
const numbers:number[] = [1,2,3,4,5,6]
const sqnumbers = numbers.map((number:number ): number=>number*number)
لكن FOR LOOP
لها إستخدمات كثيرة و إستخدامها يكون يدويا أكثر مقارنة ب MAP LOOP
المهم نرجع إلى ملف PAGE.TSX في مجلد ال DATABASE
و نقوم بتعديل على منادة الدالة حيث ستأخد ك مدخل ثاني مصفوفة من ال TAGS
نقوم بزيارة المتصفح على اللينك localhost:3000/database
فنجد أن
بقى فقط ال child blocks
طريقة إضافتها
طبعا شكل البيانات أخدته من notion api
من خلال الرابط
notion.api.blocks
مثال عن العناوين من موقع
JSON:
{
//...other keys excluded
"type": "heading_1",
//...other keys excluded
"heading_1": {
"rich_text": [{
"type": "text",
"text": {
"content": "Lacinato kale",
"link": null
}
}],
"color": "default",
"is_toggleable": false
}
}
مثال عن الفقرات
JSON:
{
//...other keys excluded
"type": "paragraph",
//...other keys excluded
"paragraph": {
"rich_text": [{
"type": "text",
"text": {
"content": "Lacinato kale",
"link": null
}
}],
"color": "default"
}
الأن قم بإكمال الكود بحيث يكون
عنةان رئيسي لون غلافة احمر محتواه negative things
فقرة بلون الأحمر محتواه سيكون مخزن داخل متغير إسمه things.negative_things
عنوان الرئيسي لونه أزرق محتواه other
فقرة بلون default بيكون مخزن داخل متغير things.other
things بيكون مدخل الدالة الثالث لذلك ستحتاج تغيير توقيع الدالة
لذلك سيكون بشكل الأتي
JavaScript:
export async function CreateApage({ title, tags ,things}: { title: string, tags:string[] ,things:child_block_data_type}) { ....}
أو
JavaScript:
export async function CreateApage({ title, tags ,things}: { title: string, tags:string[] ,things:{
negative_things: string|null,
positive_things: string|null,
other:string|null
}}) { ...}
أما عن البيانات فأصل أن تكون بشكل الأتي
JSON:
{
"type": "heading_1",
"heading_1": {
"rich_text": [{
"type": "text",
"text": {
"content": "positive things",
"link": null
}
}],
"color" : "green_background" as color,
"is_toggleable": false
}
},
{
object: 'block',
type: 'paragraph',
paragraph: {
rich_text:[
{
"type": "text",
"text": {
"content": things.positive_things,
"link": null
},
"annotations": {
"color":"green"
},
}] as rich_text_type
}
},
{
"type": "heading_1",
"heading_1": {
"rich_text": [{
"type": "text",
"text": {
"content":"negative things",
"link": null
}
}],
"color": "red_background" as color,
"is_toggleable": false
}
},
{
object: 'block',
type: 'paragraph',
paragraph: {
rich_text:[
{
"type": "text",
"text": {
"content": things.negative_things,
"link": null
},
"annotations": {
"color":"red"
},
}] as rich_text_type
}
},{
"type": "heading_1",
"heading_1": {
"rich_text": [{
"type": "text",
"text": {
"content": "other",
"link": null
}
}],
"color": "blue" as color,
"is_toggleable": false
}
},
{
object: 'block',
type: 'paragraph',
paragraph: {
rich_text:[
{
"type": "text",
"text": {
"content": things.other,
"link": null
},
"annotations": {
"color": "default"
},
}] as rich_text_type
}
}
نقوم بمناداة الدالة من الملف
page.tsx داخل مجلد database
JavaScript:
CreateApage({ title: "just a test", tags: ["some ", "random ", "words"], things: { positive_things: "just a test ", negative_things: "just a another test ", other: "just to make sure verthing works fine"} })
ندحل من متصفح على ال localhost:3000/database
تم نزور موقع notion فنجد
و الأن بقي إستخراج الصفحات
طبعا سنستخدم ال sort لترتيب البيانات بناء على شئ
فنتيجة ستكون بشكل الأتي
النتيجة
نلاحظ أن بينات عبارة عن structure
لدخول لمعلومات نحتاج نكتب إسم ال structure ثم نقطة تم إسم المعلومة
مثال لدينا structure إسمها student نريد الحصول على معلمة الإسم name فنكتب student.name
للشرح كتبت المثال الأتي
JavaScript:
export function student() {
const student = {
name:"mohamed",
firstname: "sumbel",
job: "cat",
workplace:"memes",
}
console.log(student.name)
console.log(student.firstname)
console.log(student.job)
console.log(student.workplace)
}
طبعا التنيجة ستكون
Bash:
mohamed
sumbel
cat
memes
بإستخدام هذا المعلموات يمكننا الأن أخد البينات التي نحتاجها
فالشئ الذي سنقوم به الأن أخد مصفوفة res.results
وإرجاع مصفوفة أخرى تحتوي على البيانت المهمة و التي ستكون تاريخ إناشاء تاريخ التعديل إسم الصفحة و tags الصفحة و معرف الصفحة بالتأكيد
,و هذه هي دالة ال GetTags
JavaScript:
function GetTags(result:any) {
const Tags = result.properties.Tags.multi_select.map((tag: any) => {
return {
id: tag.id, name: tag.name
}
})
return Tags;
}
طبعا إلى هنا إنتهى الجزء الأول من المشروع بقي جزء ال ui و تعديل هذه الدوال قليلا و إذافة دوال أخرى
لكن بقي بعض أشياء التي لم نتطرق إليها مثل tailwind css فرق بين typescript و javascript و أيضا موضوع approuter و مواضيع أخرى
,و هذه أشياء سنتطرق إليها في الجزء الثاني إن شاء الله
أي خطأ في مقالة يرجى التبليغ عنه لإصلاحه
و السلام عليكم
لكن بقي بعض أشياء التي لم نتطرق إليها مثل tailwind css فرق بين typescript و javascript و أيضا موضوع approuter و مواضيع أخرى
,و هذه أشياء سنتطرق إليها في الجزء الثاني إن شاء الله
أي خطأ في مقالة يرجى التبليغ عنه لإصلاحه
و السلام عليكم
المرفقات
-
1724335539863.webp138.8 KB · المشاهدات: 92
-
1724336034430.webp69.8 KB · المشاهدات: 91
-
1724336366120.webp142.5 KB · المشاهدات: 94
-
1724338190752.webp26.2 KB · المشاهدات: 92
-
1724417076929.webp50.2 KB · المشاهدات: 92
-
1724418754396.webp59.1 KB · المشاهدات: 92
-
1724431887369.webp69.5 KB · المشاهدات: 94
-
1724431906640.webp70.8 KB · المشاهدات: 91
-
1724439192827.webp72.3 KB · المشاهدات: 92
-
1724625652078.webp53.1 KB · المشاهدات: 90
-
1724625831585.webp48.8 KB · المشاهدات: 95
التعديل الأخير بواسطة المشرف: