Eklentiler (Plugins)

Projenizdeki tüm eklentiler registerPlugins() metodu ile main.js dosyanızdan çağırılırlar.

src/main.js

// Components
import App from "./App.vue";

// Composables
import { createApp } from "vue";

// Plugins
import { registerPlugins } from "@/plugins";
const app = createApp(App);

registerPlugins(app); 
app.mount("#app");

Admin Eklentisi

Admin eklentisi Olobase Admin ana kütüphanesinin projenize dahil edilmesini ve projenizdeki temel fonksiyonların konfigüre edilmesini ve çalışmasını sağlar. Takip eden örnekte admin eklentisine ait bir örnek gösteriliyor:

src/plugins/admin.js

import OlobaseAdmin from "olobase-admin";
import router from "@/router";
import i18n from "../i18n";
import store from "@/store";
import config from "@/_config";
import routes from "@/router/admin";
import PageNotFound from "@/views/Error404.vue";
import {
  jsonServerDataProvider,
  jwtAuthProvider,
} from "olobase-admin/src/providers";
import { en, tr } from "olobase-admin/src/locales";

let admin = new OlobaseAdmin(import.meta.env);
/**
 * Install admin plugin
 */
export default {
  install: (app, http, resources) => {
    admin.setOptions({
      app,
      router,
      resources,
      store,
      i18n,
      dashboard: "dashboard",
      downloadUrl: "/files/findOneById/",
      readFileUrl: "/files/readOneById/",
      title: "demo",
      routes,
      locales: { en, tr },
      dataProvider: jsonServerDataProvider(http),
      authProvider: jwtAuthProvider(http),
      http,
      canAction: null,
      // canAction: ({ resource, action, can }) => {
      //   if (can(["admin"])) {
      //     return true;
      //   }
      //   // any other custom actions on given resource and action...
      // },
      config: config,
    });
    admin.init();
    OlobaseAdmin.install(app); // install layouts & components
    app.provide("i18n", i18n);
    app.provide("router", router);
    app.provide("admin", admin); // make injectable
    app.component("PageNotFound", PageNotFound);
  },
};

Admin eklentisinin temel görevleri aşağıdaki gibidir:

  • Veri sağlayıcıları, yerel ayarları, ve yönetici rotalarını yükler.
  • Kaydetmek istediğiniz kaynakları yükler.
  • Vue Route, Vuex ve Vue I18n'nin güncel örneklerini kaydeder.
  • Yetki kontrolünün özelleştirilebilmesini sağlar.
  • Init metodu ile Olobase Olobase Admin nesnesini başlatır.
  • Error404.vue gibi genel bileşenleri Vue örneğine kayıt eder.

Konfigürasyon

OlobaseAdmin nesnesi konfigurasyon için uygulamanız tarafında bulunan src/_config.js nesnesine ihtiyaç duyar.

export default {
  //
  // va-form component global settings
  // 
  form: {
    disableExitWithoutSave: false,
  },
  dateFormat: "shortFormat",
  //
  // va-list provider global settings
  // 
  list: {
    disableGlobalSearch: false,
    disableItemsPerPage: true,
    itemsPerPage: 10,
    itemsPerPageOptions: [100],
  },
  /*
  ...
  */
}

Admin Eklentisinin Örneklenmesi

OlobaseAdmin constructor metodunun çalışması için aşağıda listelenen parametrelerin tümüne ihtiyacı vardır:

Anahtar Tür Açıklama
router VueRouter Tüm genel özel rotalarınızı içerebilen Vue Router örneği.
store Vuex.Store Otomatik kaynak API modülleri köprü kaydı için tüm özel modüllerinizi içerebilen Vue Store örneği.
i18n VueI18n Tam yerelleştirme desteği için tüm özel yerelleştirilmiş etiketlerinizi içerebilen Vue I18n örneği.
dashboard string Uygulamanızın giriş sayfasına ait rotasını belirler. Giriş sayfanızın rotasını farklılaştırmak istiyrosanız bu değere mevcut bir rota adı vermelisiniz.
downloadUrl string Dosya indirme api rotasını belirler.
readFileUrl string Dosya okuma api rotasını belirler.
title string Uygulamanızın başlığı, uygulama çubuğu başlığında ve belge başlığında sayfa başlığından sonra gösterilecektir
routes object Yönetici düzeninden devralınması gereken, kimliği doğrulanmış rotaların listesi. Tüm kaynak rotalarının CRUD sayfaları burada alt öğe olarak kaydedilecek
locales object En az bir Olobase Admin yerel ayarı sağlanmalıdır; yalnızca en ve tr dilleri %100 desteklenir.
authProvider object Kimlik doğrulama sözleşmesini uygulaması gereken kimlik doğrulama sağlayıcısı.
dataProvider object Veri sözleşmesini uygulaması gereken veri sağlayıcı.
resources array Yönetilecek tüm kaynakları içeren kaynaklar dizisi.
http object İsteğe bağlı olarak eklenen özel HTTP istemcisi, this.admin.http aracılığıyla kullanılabilir.
config object Alanlar veya girişler için bazı genel seçenekler ve bazı ayarlar için kullanılır.
canAction null|function Herhangi bir kaynağın her eylemi için özelleştirilebilir yetki fonksiyonu.

Olobase Admin akış şeması.

Olobase Admin Plugin

Vue Router

Ana VueRouter yalnızca genel sayfalara (veya vuetify-admin ile ilgili olmayan tüm diğer sayfalara) sahip olmalıdır. Bu sayfalarda herhangi bir Admin Düzeni tamamen yoktur, dolayısıyla kendi düzeninizi kullanabilirsiniz. Olobase Admin, oluşturduğu CRUD kaynak rotalarını VueRouter.addRoute() aracılığıyla eklemek için Vue Router'a ihtiyaç duyacaktır.

src/router/index.js

import { createRouter, createWebHistory } from "vue-router";

import i18n from "../i18n";
import Member from "@/layouts/Member.vue";
import Login from "@/views/Login.vue";
import ForgotPassword from "@/views/ForgotPassword";
import ResetPassword from "@/views/ResetPassword";

const routes = [
  {
    path: "/",
    redirect: "/login",
    component: Member,
    children: [
      {
        path: "/login",
        name: "login",
        component: Login,
        meta: {
          title: i18n.global.t("routes.login"),
        },
      },
      {
        path: "/forgotPassword",
        name: "forgotPassword",
        component: ForgotPassword,
        meta: {
          title: i18n.global.t("routes.forgotPassword"),
        },
      },
      {
        path: "/resetPassword",
        name: "resetPassword",
        component: ResetPassword,
        meta: {
          title: i18n.global.t("routes.resetPassword"),
        },
      },
    ],
  }
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

export default router;

Varsayılan olarak yukarıdaki gibi herhangi bir kayıt veya şifre sıfırlamanın da dahil olabileceği bir giriş sayfanız olmalıdır.

Vuex

Tüm özel store modüllerinizi buraya koyabilirsiniz. İster özel sayfalarınızda ister kaynak sayfalarınızda olsun, bunları istediğiniz yerde kullanmakta özgürsünüz. Olobase Admin, oluşturduğu API kaynakları modüllerini RegisterModule() aracılığıyla kaydettirmek için tam olarak örneklenmiş Vuex'e ihtiyaç duyacaktır.

İşte temel bir örnek:

src/store/index.js

import { createStore } from "vuex";
import axios from 'axios';

const store = createStore({
  state: {
    locale: "en",
    showDialog: false,
    confirm: false,
    resolve: null,
    reject: null,
  },
  actions: {
    setLocale({ commit }, locale) {
      commit("SET_LOCALE", locale);
    },
    openDialog({ commit, state }) {
      commit("TOGGLE_DIALOG", true);
      return new Promise((resolve, reject) => {
        state.resolve = resolve;
        state.reject = reject;
      });
    },
  },
  getters: {
    dialog(state) {
      return state.showDialog;
    },
    getLocale(state) {
      return state.locale
    }
  },
  mutations: {
    SET_LOCALE(state, locale) {
      state.locale = locale;
      axios.defaults.headers.common['Client-Locale'] = locale;
    },
    TOGGLE_DIALOG(state, bool) {
      state.showDialog = bool;
    },
    TOGGLE_DIALOG(state, bool) {
      state.showDialog = bool;
    },
    TOGGLE_AGREE(state) {
      state.resolve(true);
      state.showDialog = false;
    },
    TOGGLE_CANCEL(state) {
      state.resolve(false);
      state.showDialog = false;
    },
  },
  modules: {},
});

export default store;

Kimlikleri Doğrulanmış Rotalar

Olobase Admin'in, alt öğeler olarak kimliği doğrulanmış tüm rotaları içerecek, yukarıdaki genel rotalardan ayrı bir temel rota formatı nesnesine ihtiyacı vardır. Bu ayrılmanın temel nedeni Vue Router alt kayıt sınırlamasından kaynaklanmaktadır. Bu nedenle en azından şimdilik OlobaseAdmin yapıcısına manuel olarak enjekte edilmesi gerekiyor. Burası, kimliği doğrulanmış tüm özel sayfalarınızı kontrol paneli, profil sayfası vb. olarak yerleştirebileceğiniz yerdir.

src/router/admin.js

import AdminLayout from "@/layouts/Admin";
import Dashboard from "@/views/Dashboard";
import Account from "@/views/Account";
import Password from "@/views/Password";
import Error404 from "@/views/Error404";
import i18n from "../i18n";

export default {
  path: "",
  component: AdminLayout,
  meta: {
    title: i18n.global.t("routes.home"),
  },
  children: [
    {
      path: "/dashboard",
      name: "dashboard",
      component: Dashboard,
      meta: {
        title: i18n.global.t("routes.dashboard"),
      },
    },
    {
      path: "/account",
      name: "account",
      component: Account,
      meta: {
        title: i18n.global.t("routes.account"),
      },
    },
    {
      path: "/password",
      name: "password",
      component: Password,
      meta: {
        title: i18n.global.t("routes.password"),
      },
    },
    {
      path: "*",
      component: Error404,
      meta: {
        title: i18n.global.t("routes.notFound"),
      },
    },
  ],
};

404 Hata Sayfası

Olobase Admin tarafından çözülemeyen sayfa istekleri src/views/Error404.vue bileşenine yönlendirilir. Varsayılan 404 sayfası olarak kullanılır ve özelleştirilebilir.

Loader Eklentisi

Loader eklentisi adından anlaşılacağı gibi temel yükleme görevlerini içerir. Aşağıda bu görevler listelenmiştir.küütüphanelerinizi .

  • Kaynaklar dizinindeki tüm üçüncü taraf bileşenlerini Portal Vue, Trix ve CRUD sayfaları kaynakları olarak kaydeder.
  • Özel CSS dosyalarını içe aktarır.
  • /src/resources/ klasörünüz altındaki modüllerinizi otomatik olarak yükler.
import "./vuetify";
import Trix from "trix";
import "trix/dist/trix.css";
import "@mdi/font/css/materialdesignicons.css";
import PortalVue from "portal-vue";
import Modal from "../components/Modal";
import camelCase from "lodash/camelCase";
import upperFirst from "lodash/upperFirst";
/**
 * Autoload resources
 */
const modules = import.meta.glob('@/resources/*/*.vue', { eager: true })
/**
 * Dynamic vuetify components
 */
import {
  VAutocomplete,
  VCombobox,
} from "vuetify/components";

export default {
  install: (app) => {
    /**
     * Register portal-vue
     */
    app.use(PortalVue);
    /**
     * Register global modal
     */
    app.component('modal', Modal);
    /**
     * Explicit registering of this components because dynamic
     */
    app.component("VAutocomplete", VAutocomplete);
    app.component("VCombobox", VCombobox);
    /**
     * Register application resources automatically
     */
    for (let fileName in modules) {
      const componentConfig = modules[fileName];
      fileName = fileName
        .replace(/^\.\//, "")
        .replace(/\//, "")
        .replace(/\.\w+$/, "");
      const pathArray = fileName.split("/").slice(-2);
      const componentName = upperFirst(camelCase(pathArray[0].toLowerCase() + pathArray[1]));

      // register component
      app.component(
        componentName,
        componentConfig.default || componentConfig
      );
    }
    // end app resources
  },
};

useHttp Eklentisi

useHttp(axios) metodu bir axios örneğinden admin client elde etmek için kullanılır. Yani useHttp() metodu devreden çıkarıldığından aşağıdaki uygulamanızda aşağıdaki fonksiyonlar çalışmayacaktır.

  • authentication
  • refresh token
  • process queue
  • error parsing

Açıkça anlatmak gerekirse useHttp() metodu uygulamaya özgü axios interceptörler i axios örneğine atamış olur.

Uygulamaya ait birincil axios örneği plugins/index.js dosyası içerisinde yaratılır ve useHttp() metodu burada çalıştırılır.

src/plugins/index.js

import { useHttp } from "../plugins/useHttp";
import axios from "axios";
/**
 * Set default global http configuration
 */
axios.defaults.timeout = 10000;
axios.defaults.baseURL = import.meta.env.VITE_API_URL;
axios.defaults.headers.common['Content-Type'] = "application/json";
axios.defaults.headers.common['Client-Locale'] = i18n.global.locale.value;
axios.interceptors.request.use(
  function (config) {
    let token = localStorage.getItem("token");
    if (typeof token == "undefined" || token == "undefined" || token == "") {
      return config;
    }
    config.headers["Authorization"] = "Bearer " + token;
    return config;
  },
  function (error) {
    return Promise.reject(error);
  }
);
useHttp(axios);

src/plugins/useHttp.js

import i18n from "../i18n";
import store from "@/store";
import eventBus from "vuetify-admin/src/utils/eventBus";

let isRefreshing = false;
let failedQueue = [];
//
// https://github.com/Godofbrowser/axios-refresh-multiple-request/tree/master
// 
const processQueue = (error, token = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  failedQueue = [];
};
/**
 * Http global response settings
 */
const useHttp = function (axios) {
  let axiosInstance = axios;  
  axiosInstance.interceptors.response.use(
    (response) => {
      const statusOk = (response && response["status"] && response.status === 200) ? true : false;
      const configUrlSegments = response.config.url.split('/');
      if (
        (statusOk && configUrlSegments.includes("create")) || 
        (statusOk && configUrlSegments.includes("update"))
      ) {
        eventBus.emit("last-dialog", false)  // close edit modal window if it's opened
        store.commit("messages/show", { type: 'success', message: i18n.global.t("form.saved") });
      }
      if (statusOk &&
       cookies.get(cookieKey.token) && 
       response.config.url == "/auth/session") {
        let config = response.config;
        config._retry = false; // retry value every must be false
        const delayRetryRequest = new Promise((resolve) => {
          setTimeout(() => {
            resolve();
          }, import.meta.env.VITE_SESSION_UPDATE_TIME * 60 * 1000); // every x minutes 
        });
        return delayRetryRequest.then(() => axiosInstance(config));
      }
      return response;
    },

    /* etc .... */
}
//
// This is an example and this part of the coding has been deleted 
// so it doesn't take up much space.
//
/**
 * Export useHttp method
 */
export { useHttp };

Vuetify Eklentisi

Vuetify eklentisi, VuetifyJs kütüphanesine özgü konfigürasyonlarınızı içerir.

// Styles
import "vuetify/styles";

// Translations provided by Vuetify
import { en, tr } from "vuetify/locale";
import Trans from "@/i18n/translation";
const defaultLang = Trans.guessDefaultLocale();

// Composables
import { createVuetify } from "vuetify";

const defaultTheme = {
  dark: false,
  colors: {
    background: "#FFFFFF",
    surface: "#FFFFFF",
    primary: localStorage.getItem("themeColor")
      ? localStorage.getItem("themeColor")
      : "#0a7248",
    secondary: "#eeeeee",
    error: "#ed0505",
    info: "#00CAE3",
    // success: '#4CAF50',
    // warning: '#FB8C00',
  },
};
// Vuetify 
export default createVuetify({
  locale: {
    locale: Trans.supportedLocales.includes(defaultLang) ? defaultLang : import.meta.env.VITE_DEFAULT_LOCALE,
    fallback: "en",
    messages: { tr, en },
  },
  theme: {
    defaultTheme: "defaultTheme",
    themes: {
      defaultTheme,
    },
  },
});