Spica Engine Nedir?

Güncelleme Yayın

Headless CMS yazısının devamı olarak, Akdeniz Üniversitesi (Antalya) içerisinde bulunan bir bağımsız geliştirici takımı tarafından geliştirilen açık kaynak kodlu bir projeden bahsetmek istiyorum. Beta halindeki uygulamanın tam adı Spica Engine. Spica headless cms kategorisinde de ele alabileceğimiz ancak bundan çok daha fazlasını sunan bir yazılım geliştirme motoru. Peki, Spica tam olarak ne yapıyor? Ne tür kullanım imkanları sunuyor ve nasıl çalışıyor?

Spica Engine

Spica Engine

Spica, fonksiyonlar, policy-based yönetim, bucket mimarisi, front-end oluşturucu (composer) gibi özellikler sunan platform bağımsız bir yapı sunuyor. İlgili detaylara uygulama web sayfası spicaengine.com üzerinden ulaşabilir, yayınlanan kodları GitHub @spica-engine/spica üzerinden görüntüleyebilirsiniz. Örnek kurulum üzerinden incelemelerde bulunmak için example.spicaengine.com/spica adresini kullanabilir kullanıcı adı: spica, şifre: spica bilgileri ile giriş yapabilirsiniz.

Spica Engine Özellikleri

Spica özelliklerini en temel şekilde listeleyebiliriz;

  • Bucket modülü ile veri modelleme
  • Function modülü ile özel davranış tanımlama
  • Passport modülü ile kaynak tabanlı kimlik yönetimi
  • API öncelikli (API-first) yaklaşımıyla platform bağımsız yapı

Bu özellikler sade bir arayüz aracılığıyla kolaylıkla yönetilebilmekte. Kurulum bölümünde ve Postman üzerinden gerçekleştireceğim örnek işlemde yine detaylara değineceğim.

Spica Engine - Dashboard

Spica Engine Kurulum

Öncelikle, dokümantasyonda eksiklikler ve farklı sayfalarda bilgi uyuşmazlıkları olduğunu belirtmekte fayda var. Bu sebeple, önerim GitHub sayfasındaki yönergeleri takip etmeniz. Ben kurulum işlemini DigitalOcean üzerine oluşturduğum Docker dropleti üzerinden gerçekleştirdim. Elbette farklı seçenekler de mevcut. Ancak, kurulum için NodeJs ve Docker zorunluluk.

curl -X POST -H 'Content-Type: application/json' \
     -H 'Authorization: Bearer '$TOKEN'' -d \
    '{"name":"choose_a_name","region":"sfo2","size":"s-2vcpu-4gb","image":"docker-18-04"}' \
    "https://api.digitalocean.com/v2/droplets"

Yukarıdaki komut satırını kullanarak DigitalOcean API üzerinden hızlı bir şekilde docker imajının kurulmasını sağlayabilirsiniz. Bundan sonraki aşama artık SSH bağlantısı üzerinden yapılandırma işlemlerine geçebiliriz.

docker network create spica

Ardından MongoDB replica set’i kuralım. mongo:versiyon ile sürüm de belirtebilirsiniz.

docker run --name mongo-1 --network spica -d mongo --replSet "rs0" --bind_ip_all
docker run --name mongo-2 --network spica -d mongo --replSet "rs0" --bind_ip_all
docker run --name mongo-3 --network spica -d mongo --replSet "rs0" --bind_ip_all

Kurulum aşamasında bir sorun olmayacaktır. Ancak, yine de kontrol etmekte fayda var.

docker ps --filter=Name=mongo

Komutun uygulanmasını ardından oluşturduğumuz (ve elbette daha önce oluşturulan) mongo image container’lar listelenecektir.

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
30a2fce583f6        mongo:4.2           "docker-entrypoint.s…"   2 hours ago         Up 2 hours          27017/tcp           mongo-3
e24f07d2a466        mongo:4.2           "docker-entrypoint.s…"   2 hours ago         Up 2 hours          27017/tcp           mongo-2
5a31b846cdaf        mongo:4.2           "docker-entrypoint.s…"   2 hours ago         Up 2 hours          27017/tcp           mongo-1

Şayet ilgili container’lar listelenmemişse ancak tekrar kurulum yapmak istediğinizde hata alıyorsanız docker rm ile ilgili kurulumu kaldırıp yeniden yükleme yapabilirsiniz. Şimdi bu container’lar arasındaki ilişkiyi oluşturalım.

docker exec -it mongo-1 mongo admin --eval 'rs.initiate({ _id: "rs0", members: [{ _id: 0, host : "mongo-1" }, { _id: 1, host : "mongo-2" }, { _id: 2, host : "mongo-3", priority : 0, slaveDelay: 5, tags: { slaveDelay: "true" } }] })'

Komutun uygulanmasının ardından, işlemin başarıyla gerçekleştirildiğine dair şuna benzer bir bilgilendirme alırız.

MongoDB shell version v4.2.6
connecting to: mongodb://127.0.0.1:27017/admin?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("96fc752c-25a5-4cc3-871d-21ac9c02709b") }
MongoDB server version: 4.2.6
{
 "ok" : 1,
 "$clusterTime" : {
  "clusterTime" : Timestamp(1587810298, 1),
  "signature" : {
   "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
   "keyId" : NumberLong(0)
  }
 },
 "operationTime" : Timestamp(1587810298, 1)
}

Şimdi portlarımızı tanımlamaya geçebiliriz. Spica API için 4400, ve client için 4500 portlarını kullanacağız.

docker run \
    --name api \
    --network spica \
    -p 4400:80 \
    -e PORT=80 \
    -e DATABASE_URI="mongodb://mongo-1,mongo-2,mongo-3" \
    -e REPLICA_SET="rs0" \
    -e DATABASE_NAME=spica \
    -e DEFAULT_PASSWORD=spica \
    -e SECRET="$2b$10$shOzfYpDCy.RMgsVlwdQeONKGGzaBTfTQAjmXQNpMp4aKlLXrfZ/C" \
    -e PUBLIC_HOST=http://localhost:4400 \
    -e PERSISTENT_PATH=/tmp \
    -d spicaengine/api

Veritabanı (spica) mongodb kurulumlarında belirtmiştik, dolayısıyla en başta bir değişiklik yaptıysanız aynı değişikliği tüm süreçte takip etmelisiniz. DEFAULT_PASSWORD alanında belirtilen şifreyi istediğiniz gibi değiştirebilirsiniz. SECRET ise API tarafından kullanılacak. PUBLIC_HOST bilgisini kendi erişim bilgilerinize uygun olarak düzenleyebilirsiniz.

Son olarak diğer portumuzu da tanımlayalım.

docker run \
    --name spica \
    --network spica \
    -e BASE_URL="/" \
    -e API_URL="http://localhost:4400" \
    -p 4500:80 \
    -d spicaengine/spica

Yine, tüm container’ları listeleyelim.

docker ps

Alacağımız dönüş aşağı yukarı şu şekilde olacaktır;

CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS                  NAMES
67729c055cdd        spicaengine/spica        "sh -c '/container/s…"   About a minute ago   Up About a minute   0.0.0.0:4500->80/tcp   spica
20a0b8f4b874        spicaengine/api:latest   "/app/stacks/api/ima…"   4 minutes ago        Up 4 minutes        0.0.0.0:4400->80/tcp   api
4b42399427db        mongo                    "docker-entrypoint.s…"   9 minutes ago        Up 9 minutes        27017/tcp              mongo-3
972b06991018        mongo                    "docker-entrypoint.s…"   10 minutes ago       Up 10 minutes       27017/tcp              mongo-2
8249fdd96260        mongo                    "docker-entrypoint.s…"   10 minutes ago       Up 10 minutes       27017/tcp              mongo-1

Evet, artık panelimize erişim sağlayabiliriz; http://localhost:4500. Kullanıcı bligilerimiz; spica / spica.

Spica Engine - Dashboard

Giriş işleminin ardından sade bir arayüz üzerinden Spica Engine aracının barındırdığı özellikleri görebilmekteyiz. Bundan sonraki aşamada bir örnek işlem gerçekleştirelim ve bu sayede bu özelliklerin de nasıl kullanıldığına bir bakalım.

Spica Engine Kullanımı

İlk olarak Developer > Buckets bölümüne gidelim ve kendimize bir veri alanı oluşturalım. Spica Engine’i bir headless CMS olarak kullanacağımızı varsayarak bucket’ıma News adını verebilirim. title:string ve description:textarea ön tanımlı olarak gelen alanlar. Bu alanlara ek olarak, path:string, created date:date, modified date:date, summary:textarea, article:richtext, author:string, featured image:storage gibi alanlar oluşturabilirim. Oluşturduğum her alanın aynı zamanda View bölümüne yerleştirildiğini görebilirsiniz. Bu alanları Left, Right ve Bottom alanlarına sürükle-bırak yöntemiyle taşıyabilirsiniz. Save butonuna tıklayarak yaptığımız düzenlemeyi kayıt edelim ve örnek içeriklerimizi ekleyelim. Oluşturduğumuz News başlıklı bucket’a Content bölümü altından ulaşabiliriz. Content > News > Add New adımlarını izlediğimizde bizim oluşturduğumuz field’ların geldiğini görebilirsiniz. Uygun şekilde bu alanları doldurup içeriklerimizi kayıt altına alalım. Örnek içerikler için WHO News içeriklerini kullandım. Artık bu bilgilere API aracılığıyla erişebilir ve yeni bilgiler ekleyebilirim.

Kimlik Oluşturma

API erişimi için System > Identites adımlarını takip ederek yeni bir kimlik oluşturalım ve Policies ile bu kimliğin yetkilerini belirleyelim. Indentifier alanına bir kullanıcı adı, Password alanına da şifremizi yazalım ve bilgileri kayıt edelim. Bu bilgileri unutmamalısınız. Birazdan Postman üzerinden token almak için bu bilgilerden faydalanacağız. Yetkiler için Policies bölümünden sadece Bucket Read Only Access seçeneğini seçersek içeriklere ulaşabilir ancak içerik ekleyemeyiz. Bucket Full Access ise bize ekleme, silme ve düzenleme başta olmak üzere hem bucket hem de içerikler üzerinde yetki sağlar.

Spica Engine - Bucket

Spica API Üzerinden İçeriklere Erişim

Evet, son adımımıza geldik. Oluşturduğumuz bucket altındaki içeriklere yine oluşturduğumuz ve yetkilerini belirlediğimiz kimlik üzerinden erişeceğiz. Bu işlem için ben Postman aracını kullanacağım. Elbette herhangi bir başka client aracılığıyla da erişim sağlanabilir. Bucket işlemleri için BucketDataController ve BucketController controller’larımız var. BucketDataController GET istekleri yetki (authorization) gerektirmeksizin kullanılabilmekte. Örneğin, :4400/bucket//data ile belirttiğimiz bucketId içeriğine kolaylıkla erişebiliriz. Ancak, BucketController çok daha sınırlı bir şekilde kullanılabilmekte. O halde, önce yetkilendirme işlemimizi tamamlayalım. Az önce Identites altında oluşturduğumuz kullanıcı kimlik bilgilerini ilgili alanlara ekleyip; :4400/passport/identify?password=&identifier= GET isteğinde bulunduğumuzda Spica bize şu JSON çıktısını dönecektir.

{
    "issuer": "spica:passport",
    "token": "JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI1ZWEzZjQxYTcxYzJmYTg0MDM4YjQ2YTQiLCJpZGVudGlmaWVyIjoidGVzdHVzZXIiLCJwb2xpY2llcyI6WyJCdWNrZXRSZWFkT25seUFjY2VzcyJdLCJhdHRyaWJ1dGVzIjp7fSwiaWF0IjoxNTg3ODA0MDc3LCJleHAiOjE1ODc5NzY4NzcsImF1ZCI6InNwaWNhLmlvIiwiaXNzIjoiaHR0cDovLzEwNC4yNDguMTguMTQxOjQ0MDAifQ.Tu3s1u2TuhZNhYTUmHXlciKH8W-MPUHHQ2kf4TH7WQo",
    "schema": "JWT"
}

Bundan sonraki aşamada Header içerisinde Authorization için token içeriğini iletmemiz yetki için yeterli olacaktır. Artık yetki (authorization) gerektiren tüm işlemleri (elbette Policies altında belirtilen dahilinde) gerçekleştirebiliriz. Örneğin, bucket’ları listeleyelim; :4400/bucket. Yaptığımız GET isteğine şu şekilde bir cevap dönecektir.

[
    {
        "_id": "5ea4172471c2fa37d48b46a6",
        "title": "News",
        "description": "Describe your new bucket",
        "icon": "view_stream",
        "primary": "title",
        "readOnly": false,
        "properties": {
            "title": {
                "type": "string",
                "title": "title",
                "description": "Title of the row",
                "options": {
                    "position": "left",
                    "visible": true
                }
            },
            "description": {
                "type": "textarea",
                "title": "description",
                "description": "Description of the row",
                "options": {
                    "position": "right"
                }
            },
            "path": {
                "type": "relation",
                "description": "Description of path",
                "options": {
                    "position": "left"
                },
                "title": "Relation"
            },
            "created date": {
                "type": "date",
                "description": "Description of created date",
                "options": {
                    "position": "right"
                },
                "title": "Publised"
            },
            "modified date": {
                "type": "date",
                "description": "Description of modified date",
                "options": {
                    "position": "right"
                },
                "title": "Modified"
            },
            "summary": {
                "type": "textarea",
                "description": "Description of summary",
                "options": {
                    "position": "bottom"
                },
                "title": "Summary"
            },
            "article": {
                "type": "richtext",
                "description": "Description of article",
                "options": {
                    "position": "bottom"
                },
                "title": "Content"
            },
            "author": {
                "type": "string",
                "title": "author",
                "description": "Description of author",
                "options": {
                    "position": "left"
                }
            },
            "featured image": {
                "type": "storage",
                "description": "Description of featured image",
                "options": {
                    "position": "left"
                },
                "title": "Featured Image"
            },
            "url": {
                "type": "string",
                "title": "URL",
                "description": "Description of URL",
                "options": {
                    "position": "bottom"
                }
            },
            "categories": {
                "type": "array",
                "description": "Description of Categories",
                "options": {
                    "position": "bottom"
                },
                "items": {
                    "type": "string",
                    "title": "Local"
                },
                "title": "Categories",
                "uniqueItems": false
            }
        }
    }
]

Bir bucket (örneğin News) altındaki içerikleri listeleyelim; :4400/bucket//data.

[
    {
        "_id": "5ea41adc71c2fae0078b46a9",
        "title": "Viet Nam adopts WHO outbreak investigation tool for COVID-19, other infectious diseases",
        "author": "CEA",
        "created date": "2020-04-25T11:10:09.000Z",
        "modified date": "2020-04-25T11:10:13.000Z",
        "summary": "Hanoi, 23 March 2020 – Viet Nam acquired new technology and skills for disease outbreak investigation as the World Health Organization (WHO) conducted a series of training on Go.Data, an outbreak investigation tool for field data collection during outbreaks of infectious diseases and public health emergencies. The series of trainings, which ran during first two weeks of March 2020 in Ha Noi and Ho Chi Minh City, was part of WHO’s support to the country’s response to the COVID-19 outbreak.",
        "article": "<p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69); text-align: center;\"><em>Mr Armand&nbsp;</em><em>Bejtullahu</em><em>, Go.Data project lead at WHO, led the series of Go.Data trainings in Viet Nam (Photo: WHO)</em></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Hanoi, 23&nbsp;March 2020 – Viet Nam acquired new technology and skills for disease outbreak investigation as the World Health Organization (WHO) conducted a series of training on Go.Data, an outbreak investigation tool for field data collection during outbreaks of infectious diseases and public health emergencies. The series of trainings, which ran during first two weeks of March 2020 in Ha Noi and Ho Chi Minh City, was part of WHO’s support to the country’s response to the COVID-19 outbreak.</p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Participants of the trainings included epidemiologists, members of rapid response teams (RRTs) and other frontline workers during disease outbreaks. Go.Data includes functionality for case investigation, contact tracing and follow-up, and visualization of chains of transmission, including secure real-time data exchange. This would facilitate timely situation monitoring and response as investigations take place. The tool is also flexible enough so that response teams can tailor its functionality to a variety of outbreak scenarios or implement it for concurrent outbreaks.</p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">“An efficient resource for data sharing and establishment of epidemiological links is key to the response to any disease outbreak. WHO, in collaboration with the Global Outbreak Alert and Response Network (GOARN), has made tremendous efforts in rendering tools, such as Go.Data, to countries, including Viet Nam, as they manage outbreaks of infectious diseases,” said Dr Kidong Park, WHO Representative in Viet Nam. “The introduction of Go.Data in the country is very timely and will hopefully bring into the table innovative solutions, especially as the country now faces COVID-19. We look forward to working further with the Ministry of Health and other partners to ensure effective use of this tool in support of our responders on the ground,” he continued.</p>",
        "url": "viet-nam-adopts-who-outbreak-investigation-tool",
        "categories": []
    },
    {
        "_id": "5ea41b1d71c2fa793c8b46aa",
        "title": "WHO Director-General's opening remarks at the launch of the Access to COVID-19 Tools Accelerator",
        "author": "CEA",
        "created date": "2020-04-25T11:11:49.000Z",
        "modified date": "2020-04-23T11:11:53.000Z",
        "summary": "Your Excellencies,\n\nGood morning, good afternoon and good evening.\n\nThe COVID-19 pandemic is an unprecedented global crisis that has been met with an unprecedented global response.\n\nResearch and development have played a central role.\n\nSince January, WHO has been working with thousands of researchers all over the world to accelerate and track vaccine development - from developing animal models to clinical trial designs, and everything in between.\n\nWe’ve also developed diagnostics that are being used all over the world;\n\nAnd we’re coordinating a global trial on the safety and efficacy of four therapeutics against COVID-19.\n\nThe world needs these tools, and it needs them fast.",
        "article": "<p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Your Excellencies,<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Good morning, good afternoon and good evening.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">The COVID-19 pandemic is an unprecedented global crisis that has been met with an unprecedented global response.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Research and development have played a central role.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Since January, WHO has been working with thousands of researchers all over the world to accelerate and track vaccine development - from developing animal models to clinical trial designs, and everything in between.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">We’ve also developed diagnostics that are being used all over the world;<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">And we’re coordinating a global trial on the safety and efficacy of four therapeutics against COVID-19.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">The world needs these tools, and it needs them fast.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Past experience has taught us that even when tools are available, they have been not been equally available to all.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">We cannot allow that to happen.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Today, WHO is proud to be uniting with many partners to launch the Access to COVID-19 Tools Accelerator, or the ACT Accelerator.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">This is a landmark collaboration to accelerate the development, production and equitable distribution of vaccines, diagnostics, and therapeutics for COVID-19.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Our shared commitment is to ensure&nbsp;<strong><span style=\"text-decoration-line: underline;\">all</span></strong>&nbsp;people have access to&nbsp;<strong><span style=\"text-decoration-line: underline;\">all</span></strong>&nbsp;the tools to defeat COVID-19.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">The ACT Accelerator brings together the combined power of several organizations to work with speed and scale.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Each of us are doing great work, but we cannot work alone.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">We’re coming together to work in new ways to identify challenges and solutions together.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">I am especially grateful to President Emmanuel Macron, President Ursula von der Leyen and Bill and Melinda Gates for their leadership and partnership in co-hosting this ACT Accelerator launch.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">We’re also grateful for the support of many world leaders, who you will hear from today.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">And I would especially like to thank Sir Andrew Witty and Dr Ngozi Okonjo-Iweala for agreeing to act as Special Envoys for the ACT Accelerator.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">We are facing a common threat, which we can only defeat with a common approach.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">I would now like to invite the other co-hosts to speak, beginning with His Excellency, President Emmanuel Macron.<br></p><p style=\"font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 24px; font-stretch: normal; color: rgb(60, 66, 69);\">Monsieur le Président, you have the floor.&nbsp;</p>",
        "url": "who-director-general-s-opening-remarks",
        "categories": []
    }
]

API erişimleri ve ilgili diğer detaylar için Spica API sayfasını inceleyebilirsiniz. Şimdilik değineceğim konular bu kadar. Bir sonraki yazıda Vue.js aracılığıyla basit bir To Do List uygulaması hazırlayacağım. Sizin kullandığınız örnekler var ise mesaj olarak iletirseniz bu sayfa altında paylaşabilirim.