⛩️

Vue.jsを使って管理画面を作る

2021/07/05に公開

はじめに

Cloud9 + Vue.jsを使って管理画面を作成するチュートリアルとなります。

管理画面テンプレートの導入

Cloud9のターミナルで以下実行します。

Cloud9の基本的な操作方法は以下を参考にしてください。
https://26gram.com/how-to-use-cloud9

Core UI のダウンロード

# リポジトリのクローン
git clone https://github.com/coreui/coreui-free-vue-admin-template.git CoreUI-Vue

# ダウンロードしたCore UIのディレクトリに移動
cd CoreUI-Vue

# パッケージをインストール
npm install

Vue 設定ファイルの更新

/CoreUI-Vue/vue.config.js
module.exports = {
  // 以下追加
  devServer: {
    disableHostCheck: true
  },
  // 以上追加
  lintOnSave: false,
  runtimeCompiler: true,
  configureWebpack: {
    //Necessary to run npm link https://webpack.js.org/configuration/resolve/#resolve-symlinks
    resolve: {
       symlinks: false
    }
  },
  transpileDependencies: [
    '@coreui/utils',
    '@coreui/vue'
  ]
}

セキュリティグループの設定

画面右上にあるManage EC2 Instanceを選択

EC2インスタンスにチェックを入れてセキュリティグループを選択

インバウンドルールを編集を選択

ルールを追加をクリックして、左から順に「カスタムTCP」、「8080」、「マイIP」を選択

テストサーバを起動

Cloud9に戻りテストサーバを起動します。

npm run serve

アプリケーションにアクセス

Cloud9のプレビューボタンをクリックして表示できたらOKです。

プレビュー画面の右上のボタンをクリックすると別タブで大きく表示できます。

管理画面のカスタマイズ

管理画面にTodosページを追加してみましょう。

テストサーバを停止

テストサーバを停止します。
Cloud9のnpm run serveを実行しているターミナルを選択してctrl + cを押します。


画面を選択した状態でctrl(Control) + c(MacはCommandと間違えないように注意)

ナビゲーションメニューにTodosを追加

既存のファイルを以下のように編集します。

/CoreUI-Vue/src/containers/_nav.js
export default [
  {
    _name: 'CSidebarNav',
    _children: [
      // 以下追加
      {
        _name: 'CSidebarNavItem',
        name: 'Todos',
        to: '/todos',
        icon: 'cil-check',
      },
      // 以上追加
      {
        _name: 'CSidebarNavItem',
        name: 'Dashboard',
        to: '/dashboard',
        icon: 'cil-speedometer',
        badge: {
          color: 'primary',
          text: 'NEW'
        }
      },
(以下省略)
/CoreUI-Vue/src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'

// Containers
const TheContainer = () => import('@/containers/TheContainer')

// Views
const Dashboard = () => import('@/views/Dashboard')

const Colors = () => import('@/views/theme/Colors')
const Typography = () => import('@/views/theme/Typography')

const Charts = () => import('@/views/charts/Charts')
const Widgets = () => import('@/views/widgets/Widgets')

// Views - Components
const Cards = () => import('@/views/base/Cards')
const Forms = () => import('@/views/base/Forms')
const Switches = () => import('@/views/base/Switches')
const Tables = () => import('@/views/base/Tables')
const Tabs = () => import('@/views/base/Tabs')
const Breadcrumbs = () => import('@/views/base/Breadcrumbs')
const Carousels = () => import('@/views/base/Carousels')
const Collapses = () => import('@/views/base/Collapses')
const Jumbotrons = () => import('@/views/base/Jumbotrons')
const ListGroups = () => import('@/views/base/ListGroups')
const Navs = () => import('@/views/base/Navs')
const Navbars = () => import('@/views/base/Navbars')
const Paginations = () => import('@/views/base/Paginations')
const Popovers = () => import('@/views/base/Popovers')
const ProgressBars = () => import('@/views/base/ProgressBars')
const Tooltips = () => import('@/views/base/Tooltips')

// Views - Buttons
const StandardButtons = () => import('@/views/buttons/StandardButtons')
const ButtonGroups = () => import('@/views/buttons/ButtonGroups')
const Dropdowns = () => import('@/views/buttons/Dropdowns')
const BrandButtons = () => import('@/views/buttons/BrandButtons')

// Views - Icons
const CoreUIIcons = () => import('@/views/icons/CoreUIIcons')
const Brands = () => import('@/views/icons/Brands')
const Flags = () => import('@/views/icons/Flags')

// Views - Notifications
const Alerts = () => import('@/views/notifications/Alerts')
const Badges = () => import('@/views/notifications/Badges')
const Modals = () => import('@/views/notifications/Modals')

// Views - Pages
const Page404 = () => import('@/views/pages/Page404')
const Page500 = () => import('@/views/pages/Page500')
const Login = () => import('@/views/pages/Login')
const Register = () => import('@/views/pages/Register')

// Users
const Users = () => import('@/views/users/Users')
const User = () => import('@/views/users/User')

// -- 以下追加 --
// Todos
const Todos = () => import('@/views/todos/Todos')
// -- 以上追加 --

Vue.use(Router)

export default new Router({
  mode: 'hash', // https://router.vuejs.org/api/#mode
  linkActiveClass: 'active',
  scrollBehavior: () => ({ y: 0 }),
  routes: configRoutes()
})

function configRoutes () {
  return [
    {
      path: '/',
      redirect: '/dashboard',
      name: 'Home',
      component: TheContainer,
      children: [
        {
          path: 'dashboard',
          name: 'Dashboard',
          component: Dashboard
        },
        {
          path: 'theme',
          redirect: '/theme/colors',
          name: 'Theme',
          component: {
            render (c) { return c('router-view') }
          },
          children: [
            {
              path: 'colors',
              name: 'Colors',
              component: Colors
            },
            {
              path: 'typography',
              name: 'Typography',
              component: Typography
            }
          ]
        },
        {
          path: 'charts',
          name: 'Charts',
          component: Charts
        },
        {
          path: 'widgets',
          name: 'Widgets',
          component: Widgets
        },
        // 以下追加
        {
          path: 'todos',
          name: 'Todos',
          component: Todos
        },
        // 以上追加
        {
          path: 'users',
          meta: {
            label: 'Users'
          },
          component: {
            render(c) {
              return c('router-view')
            }
          },
          children: [
            {
              path: '',
              name: 'Users',
              component: Users
            },
            {
              path: ':id',
              meta: {
                label: 'User Details'
              },
              name: 'User',
              component: User
            }
          ]
        },
(以下省略)

TodosページとTodoデータの追加

/CoreUI-Vue/src/viewstodosディレクトリを追加します。

追加したtodosディレクトリにTodos.vueファイルと、TodosData.jsファイルを作成します。

/CoreUI-Vue/src/views/todos/TodosData.js
const todosData = [
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut nam facilis et officia qui",
    "completed": false
  },
  {
    "userId": 1,
    "id": 3,
    "title": "fugiat veniam minus",
    "completed": false
  },
  {
    "userId": 1,
    "id": 4,
    "title": "et porro tempora",
    "completed": true
  },
  {
    "userId": 1,
    "id": 5,
    "title": "laboriosam mollitia et enim quasi adipisci quia provident illum",
    "completed": false
  },
  {
    "userId": 1,
    "id": 6,
    "title": "qui ullam ratione quibusdam voluptatem quia omnis",
    "completed": false
  },
  {
    "userId": 1,
    "id": 7,
    "title": "illo expedita consequatur quia in",
    "completed": false
  },
  {
    "userId": 1,
    "id": 8,
    "title": "quo adipisci enim quam ut ab",
    "completed": true
  },
  {
    "userId": 1,
    "id": 9,
    "title": "molestiae perspiciatis ipsa",
    "completed": false
  },
  {
    "userId": 1,
    "id": 10,
    "title": "illo est ratione doloremque quia maiores aut",
    "completed": true
  },
  {
    "userId": 1,
    "id": 11,
    "title": "vero rerum temporibus dolor",
    "completed": true
  },
  {
    "userId": 1,
    "id": 12,
    "title": "ipsa repellendus fugit nisi",
    "completed": true
  },
  {
    "userId": 1,
    "id": 13,
    "title": "et doloremque nulla",
    "completed": false
  },
  {
    "userId": 1,
    "id": 14,
    "title": "repellendus sunt dolores architecto voluptatum",
    "completed": true
  },
  {
    "userId": 1,
    "id": 15,
    "title": "ab voluptatum amet voluptas",
    "completed": true
  },
  {
    "userId": 1,
    "id": 16,
    "title": "accusamus eos facilis sint et aut voluptatem",
    "completed": true
  },
  {
    "userId": 1,
    "id": 17,
    "title": "quo laboriosam deleniti aut qui",
    "completed": true
  },
  {
    "userId": 1,
    "id": 18,
    "title": "dolorum est consequatur ea mollitia in culpa",
    "completed": false
  },
  {
    "userId": 1,
    "id": 19,
    "title": "molestiae ipsa aut voluptatibus pariatur dolor nihil",
    "completed": true
  },
  {
    "userId": 1,
    "id": 20,
    "title": "ullam nobis libero sapiente ad optio sint",
    "completed": true
  }
]

export default todosData
/CoreUI-Vue/src/views/todos/Todos.vue
<template>
  <CRow>
    <CCol col="12" xl="8">
      <CCard>
        <CCardHeader>
          Todos
        </CCardHeader>
        <CCardBody>
          <CDataTable
            hover
            striped
            :items="items"
            :fields="fields"
            :items-per-page="5"
            clickable-rows
            :active-page="activePage"
            :pagination="{ doubleArrows: false, align: 'center'}"
            @page-change="pageChange"
          >
            <template #completed="data">
              <td>
                <CBadge :color="getBadge(data.item.completed)">
                  {{data.item.completed}}
                </CBadge>
              </td>
            </template>
          </CDataTable>
        </CCardBody>
      </CCard>
    </CCol>
  </CRow>
</template>

<script>
import todosData from './TodosData'
export default {
  name: 'Todos',
  data () {
    return {
      items: todosData,
      fields: [
        { key: 'userId' },
        { key: 'id' },
        { key: 'title' },
        { key: 'completed' }
      ],
      activePage: 1
    }
  },
  watch: {
    $route: {
      immediate: true,
      handler (route) {
        if (route.query && route.query.page) {
          this.activePage = Number(route.query.page)
        }
      }
    }
  },
  methods: {
    getBadge (status) {
      switch (status) {
        case true: return 'success'
        case false: return 'danger'
        default: 'primary'
      }
    },
    pageChange (val) {
      this.$router.push({ query: { page: val }})
    }
  }
}
</script>

テストサーバを起動

テストサーバを起動します。

npm run serve

Todosページにアクセス

画面左のナビゲーションメニューにTodosが追加されているのでクリックします。

Todoの一覧が表示されていればOKです。

APIを使ったデータの読み込み

以下のAPIで取得できるJSONデータを使ってTodoリストを作成します。

https://jsonplaceholder.typicode.com/users/2/todos

Cloud9のターミナルに戻ります。

テストサーバを停止

Cloud9のnpm run serveを実行しているターミナルを選択してctrl + cを押します。

axiosのインストール

npm install axios

axiosのGET処理を追加

axiosでAPIからTodoデータを取得する処理を追加します。

Todosテーブルの読み込むデータをitemsからfetchItemsに変更するため、12行目を :items="fetchItems"に更新しています。

/CoreUI-Vue/src/views/todos/Todos.vue
<template>
  <CRow>
    <CCol col="12" xl="8">
      <CCard>
        <CCardHeader>
          Todos
        </CCardHeader>
        <CCardBody>
          <CDataTable
            hover
            striped
            :items="fetchItems"
            :fields="fields"
            :items-per-page="5"
            clickable-rows
            :active-page="activePage"
            :pagination="{ doubleArrows: false, align: 'center'}"
            @page-change="pageChange"
          >
            <template #completed="data">
              <td>
                <CBadge :color="getBadge(data.item.completed)">
                  {{data.item.completed}}
                </CBadge>
              </td>
            </template>
          </CDataTable>
        </CCardBody>
      </CCard>
    </CCol>
  </CRow>
</template>

<script>
import todosData from './TodosData'
import axios from 'axios' // 追加
export default {
  name: 'Todos',
  data () {
    return {
      items: todosData,
      fetchItems: [], // 追加
      fields: [
        { key: 'userId' },
        { key: 'id' },
        { key: 'title' },
        { key: 'completed' }
      ],
      activePage: 1
    }
  },
  watch: {
    $route: {
      immediate: true,
      handler (route) {
        if (route.query && route.query.page) {
          this.activePage = Number(route.query.page)
        }
      }
    }
  },
  // 以下追加
  mounted () {
    this.getTodos()
  },
  // 以上追加
  methods: {
    // 以下追加
    getTodos() {
      axios.get('https://jsonplaceholder.typicode.com/users/2/todos')
        .then(response => (this.fetchItems = response.data))
    },
    // 以上追加
    getBadge (status) {
      switch (status) {
        case true: return 'success'
        case false: return 'danger'
        default: 'primary'
      }
    },
    pageChange (val) {
      this.$router.push({ query: { page: val }})
    }
  }
}
</script>

テストサーバを起動

テストサーバを起動します。

npm run serve

Todosページにアクセス

Todoの一覧の内容がUser Idが2のデータに変わっていればOKです。

Discussion