Published on

Lepkom Golang Pertemuan 7

Authors

Kodingan Lepkom Golang Pertemuan 7

Berikut ini adalah kodingan pertemuan 7 pada vmlepkom Gunadarma.

jadi file yang dibutuhkan sebagai berikut :

  • main.go
  • mahasiswa.html
  • element
    • form-add.html
    • form-delete.html
    • form-edit.html
  • Frameworks Polymer
main.go
package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"mime"
	"net/http"
	"os"
	"path/filepath"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
)

type spaHandler struct {
	staticPath string
	indexPath  string
}
type Mahasiswa struct {
	Id      int    `json:"id"`
	Npm     string `json:"npm"`
	Nama    string `json:"nama"`
	Kelas   string `json:"kelas"`
	Profile string `json:"profile"`
}
type ResponseAllData struct {
	Status bool        `json:"status"`
	Data   []Mahasiswa `json:"data"`
}
type ResponseData struct {
	Status bool      `json:"status"`
	Data   Mahasiswa `json:"data"`
}
type ResponseMessage struct {
	Status  bool   `json:"status"`
	Message string `json:"message"`
}
type ResponseError struct {
	Status bool   `json:"status"`
	Error  string `json:"error"`
}

func dbConn() (db *sql.DB) {
	dbDriver := "mysql"
	dbName := "haafidz_52418987"
	dbUser := "root"
	dbPass := ""
	db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(localhost)/"+dbName)
	if err != nil {
		panic(err.Error())
	}
	return db
}
func getAllMahasiswa(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var response ResponseAllData
	var mahasiswa Mahasiswa
	var mhs []Mahasiswa
	db := dbConn()
	rows, err := db.Query("SELECT * FROM mahasiswa")
	defer db.Close()
	if err != nil {
		log.Print(err.Error())
	}
	for rows.Next() {
		err := rows.Scan(&mahasiswa.Id, &mahasiswa.Npm, &mahasiswa.Nama, &mahasiswa.Kelas, &mahasiswa.Profile)
		if err != nil {
			log.Print(err.Error())
		} else {
			mhs = append(mhs, mahasiswa)
		}
	}
	response.Status = true
	response.Data = mhs
	json.NewEncoder(w).Encode(response)
	return
}
func getMahasiswa(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var response ResponseData
	var responseErr ResponseError
	var mahasiswa Mahasiswa
	db := dbConn()
	defer db.Close()
	params := mux.Vars(r)
	rows := db.QueryRow("SELECT * FROM mahasiswa WHERE id=?", params["id"])
	err := rows.Scan(&mahasiswa.Id, &mahasiswa.Npm, &mahasiswa.Nama, &mahasiswa.Kelas, &mahasiswa.Profile)
	if err != nil && err == sql.ErrNoRows {
		responseErr.Status = false
		responseErr.Error = "Mahasiswa tidak ditemukan"
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(responseErr)
		return
	}
	response.Status = true
	response.Data = mahasiswa
	json.NewEncoder(w).Encode(response)
	return
}
func getMahasiswaByName(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var mahasiswa Mahasiswa
	var mhs []Mahasiswa
	var response ResponseAllData
	db := dbConn()
	defer db.Close()
	params := mux.Vars(r)
	query := fmt.Sprintf("SELECT * FROM mahasiswa WHERE nama LIKE '%s%%'", params["keyword"])
	rows, err := db.Query(query)
	if err != nil {
		log.Print(err.Error())
	}
	for rows.Next() {
		if err := rows.Scan(&mahasiswa.Id, &mahasiswa.Npm, &mahasiswa.Nama, &mahasiswa.Kelas, &mahasiswa.Profile); err != nil {
			log.Print(err.Error())
		}
		mhs = append(mhs, mahasiswa)
	}
	response.Status = true
	response.Data = mhs
	json.NewEncoder(w).Encode(response)
	return
}
func createMahasiswa(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var response ResponseMessage
	db := dbConn()
	defer db.Close()
	err := r.ParseForm()
	if err != nil {
		log.Print(err.Error())
	}
	npm := r.Form.Get("npm")
	nama := r.Form.Get("nama")
	kelas := r.Form.Get("kelas")
	profile := "gambar1.jpg"
	rows, err := db.Prepare("INSERT INTO mahasiswa(npm, nama, kelas, profile) VALUES(?, ?, ?, ?)")
	if err != nil {
		log.Print(err.Error())
	}
	rows.Exec(npm, nama, kelas, profile)
	response.Status = true
	response.Message = "Mahasiswa berhasil ditambahkan"
	log.Print(response.Message)
	json.NewEncoder(w).Encode(response)
}
func updateMahasiswa(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var response ResponseMessage
	var responseErr ResponseError
	var mahasiswa Mahasiswa
	db := dbConn()
	defer db.Close()
	err := r.ParseForm()
	if err != nil {
		log.Print(err.Error())
	}
	id := r.Form.Get("id")
	npm := r.Form.Get("npm")
	nama := r.Form.Get("nama")
	kelas := r.Form.Get("kelas")
	rows := db.QueryRow("SELECT id FROM mahasiswa WHERE id=?", id)
	if err := rows.Scan(&mahasiswa.Id); err != nil && err == sql.ErrNoRows {
		responseErr.Status = false
		responseErr.Error = "Mahasiswa tidak ditemukan"
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(responseErr)
		return
	}
	update, err := db.Prepare("UPDATE mahasiswa SET npm=?, nama=?, kelas=? WHERE id=?")
	if err != nil {
		log.Print(err.Error())
	}
	update.Exec(npm, nama, kelas, id)
	response.Status = true
	response.Message = "Data mahasiswa berhasil diubah"
	log.Print(response.Message)
	json.NewEncoder(w).Encode(response)
	return
}
func deleteMahasiswa(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-type", "application/json")
	var mahasiswa Mahasiswa
	var response ResponseMessage
	var responseErr ResponseError
	db := dbConn()
	defer db.Close()
	params := mux.Vars(r)
	rows := db.QueryRow("SELECT id FROM mahasiswa WHERE id=?", params["id"])
	if err := rows.Scan(&mahasiswa.Id); err != nil && err == sql.ErrNoRows {
		responseErr.Status = false
		responseErr.Error = "Mahasiswa tidak ditemukan"
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(responseErr)
		return
	}
	delete, err := db.Prepare("DELETE FROM mahasiswa WHERE id=?")
	if err != nil {
		log.Print(err.Error())
	}
	delete.Exec(params["id"])
	response.Status = true
	response.Message = "Data mahasiswa berhasil dihapus"
	log.Print(response.Message)
	json.NewEncoder(w).Encode(response)
	return
}
func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path := filepath.Join(h.staticPath, r.URL.Path)
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		http.ServeFile(w, r, filepath.Join(h.staticPath, h.indexPath))
		return
	} else if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r)
}
func main() {
	r := mux.NewRouter().StrictSlash(true)
	mime.AddExtensionType(".js", "application/javascript")
	r.HandleFunc("/api/mahasiswa", getAllMahasiswa).Methods("GET")
	r.HandleFunc("/api/mahasiswa/{id}", getMahasiswa).Methods("GET")
	r.HandleFunc("/api/mahasiswa", createMahasiswa).Methods("POST")
	r.HandleFunc("/api/mahasiswa", updateMahasiswa).Methods("PUT")
	r.HandleFunc("/api/mahasiswa/{id}", deleteMahasiswa).Methods("DELETE")
	r.HandleFunc("/mahasiswa/search/{keyword}", getMahasiswaByName).Methods("GET")
	spa := spaHandler{staticPath: "polymer", indexPath: "index.html"}
	r.PathPrefix("/").Handler(spa)
	srv := &http.Server{
		Handler:      r,
		Addr:         "localhost:8081",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	log.Print("Server berjalan di http://localhost:8081")
	srv.ListenAndServe()
}
mahasiswa.html
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../bower_components/vaadin-grid/theme/material/vaadin-grid.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-dialog/paper-dialog.html">
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="element/form-add.html">
<link rel="import" href="element/form-edit.html">
<link rel="import" href="element/form-delete.html">

<dom-module id="mahasiswa-page">
  <template>
    <style include="shared-styles">
      :host {
        display: block;

        padding: 10px;
      }
    </style>
    <custom-style>
      <style is="custom-style">
        paper-input-container {
          width: 30%;
          float: right;
        }

        paper-dialog#deleteModal {
          width: 250px;
          max-width: 250px;
        }

        .warning,
        .danger {
          margin-left: -20px;
        }
      </style>
    </custom-style>

    <div class="card">
      <h1>Data Mahasiswa</h1>
      <p>Data Mahasiswa yang terdapat pada database</p>
      <template is="dom-if" if="[[success]]">
        <p class="alert-success"><strong>Message:</strong> [[success]]</p>
      </template>

      <!-- Get data from rest api -->
      <iron-ajax auto url="{{url}}" method="{{method}}" handle-as="json" content-type="application-json"
        last-response="{{response}}"></iron-ajax>
      <paper-button raised class="link" style="margin-bottom: 20px;" on-click="openAddModal">Tambah Data</paper-button>
      <paper-input-container no-label-float>
        <label slot="label">Search..</label>
        <iron-input slot="input">
          <input type="text" value="{{keyword::input}}" width="30%">
        </iron-input>
      </paper-input-container>

      <!-- Datatable -->
      <vaadin-grid items="{{response.data}}">
        <vaadin-grid-column width="50px">
          <template class="header">#</template>
          <template>
            <div>[[index]]</div>
          </template>
        </vaadin-grid-column>
        <vaadin-grid-column width="80px">
          <template class="header">Profile</template>
          <template>
            <img src="/img/[[item.profile]]" alt="profile" width="20px">
          </template>
        </vaadin-grid-column>
        <vaadin-grid-column>
          <template class="header">Npm</template>
          <template>
            <div>[[item.npm]]</div>
          </template>
        </vaadin-grid-column>
        <vaadin-grid-column width="150px">
          <template class="header">Nama</template>
          <template>
            <div>[[item.nama]]</div>
          </template>
        </vaadin-grid-column>
        <vaadin-grid-column>
          <template class="header">Kelas</template>
          <template>
            <div>[[item.kelas]]</div>
          </template>
        </vaadin-grid-column>
        <vaadin-grid-column width="200px">
          <template class="header">Action</template>
          <template>
            <paper-button id="[[item.id]]" class="warning" on-click="openEditModal">Edit
            </paper-button>
            <paper-button id="[[item.id]]" class="danger" on-click="openDeleteModal">Delete
            </paper-button>
          </template>
        </vaadin-grid-column>
      </vaadin-grid>
      <!-- End of datatable -->

      <!-- Crud view modal -->
      <paper-dialog id="addModal" with-backdrop>
        <form-add success="{{success}}" response="{{response}}"></form-add>
      </paper-dialog>
      <paper-dialog id="editModal" with-backdrop>
        <form-edit uid="{{uid}}" success="{{success}}" response="{{response}}"></form-edit>
      </paper-dialog>
      <paper-dialog id="deleteModal" with-backdrop>
        <form-delete uid="{{uid}}" success="{{success}}" response="{{response}}"></form-delete>
      </paper-dialog>
      <!-- End of modal -->

    </div>
  </template>

  <script>
    class MahasiswaPage extends Polymer.Element {
      static get is() { return 'mahasiswa-page'; }

      static get properties() {
        return {
          response: {
            type: Object,
          },
          keyword: {
            type: String,
            value: ''
          },
          url: {
            computed: '_computeUrl(keyword)'
          },
          method: {
            type: String,
            value: "GET"
          },
          success: String,
          uid: {
            type: Number,
            notify: true
          }
        }
      }

      _computeUrl(keyword) {
        if (keyword) {
          return ['/mahasiswa/search', keyword].join('/');
        } else {
          return '/api/mahasiswa';
        }
      }

      openAddModal() {
        this.$.addModal.open();
      }

      openEditModal(e) {
        this.uid = e.target.id;
        this.$.editModal.open();
      }

      openDeleteModal(e) {
        this.uid = e.target.id;
        this.$.deleteModal.open();
      }
    }

    window.customElements.define(MahasiswaPage.is, MahasiswaPage);
  </script>
</dom-module>

Berikut kode ini berada pada folder element.

form-add.html
<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.gi
thub.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIB
UTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENT
S.txt
-->
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../bower_components/iron-input/iron-input.html">
<link rel="import" href="../shared-styles.html">

<dom-module id="form-add">
    <template>
        <style include="shared-styles">
            :host {
                display: block;
                padding: 10px;
            }
        </style>

        <h2>Tambah Data User</h2>
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.npm::input}}" placeholder="Npm">
            </iron-input>
        </paper-input-container>
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.nama::input}}" placeholder="Nama">
            </iron-input>
        </paper-input-container>
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.kelas::input}}" placeholder="Kelas">
            </iron-input>
        </paper-input-container>
        <div class="buttons">
            <paper-button raised class="link" on-click="addMahasiswa" style="margin-top: 20px;" dialog-confirm>Tambah Data
            </paper-button>
        </div>

        <iron-ajax auto id="mahasiswaAjax" url="{{url}}" method="{{method}}" handle-as="text"
            content-type="application/json" on-response="_handleInsert">
            </iron-ajax>
    </template>

    <script>
        class FormAdd extends Polymer.Element {
            static get is() { return 'form-add'; }

            static get properties() {
                return {
                    formData: {
                        type: Object,
                        value: function () {
                            return { id: 0, npm: '', nama: '', kelas: '' }
                        }
                    },
                    url: {
                        type: String,
                        value: '/api/mahasiswa'
                    },
                    method: {
                        type: String,
                        value: 'GET'
                    },
                    success: {
                        type: String,
                        notify: true
                    },
                    response: {
                        type: Object,
                        notify: true
                    }
                }
            }

            addMahasiswa() {
                this.url = '/api/mahasiswa';
                this.method = 'POST';
                this.success = 'Data mahasiswa berhasil ditambahkan';
                this.$.mahasiswaAjax.params = this.formData;
                this.formData = {};
            }
            _handleInsert(e) {
                this.method = 'GET';
                this.set('response', JSON.parse(e.detail.response));
            }
        }

        window.customElements.define(FormAdd.is, FormAdd);
    </script>
</dom-module>
form-delete.html
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../shared-styles.html">

<dom-module id="form-delete">
    <template>
        <style include="shared-styles">
            :host {
                display: block;

                padding: 10px;
            }
        </style>

        <h2>Yakin hapus data?</h2>

        <div class="buttons">
            <paper-button class="link" dialog-dismiss>Batal</paper-button>
            <paper-button class="danger" on-click="deleteMahasiswa" raised dialog-confirm>Hapus</paper-button>
        </div>

        <iron-ajax auto url="{{url}}" method="{{method}}" handle-as="json" content-type="application/json"
            on-response="_handleDelete"></iron-ajax>
    </template>

    <script>
        class FormDelete extends Polymer.Element {
            static get is() { return 'form-delete'; }

            static get properties() {
                return {
                    uid: Number,
                    url: String,
                    method: String,
                    success: {
                        type: String,
                        notify: true
                    },
                    response: {
                        type: Object,
                        notify: true
                    }
                }
            }

            deleteMahasiswa() {
                this.method = 'DELETE';
                this.url = '/api/mahasiswa/' + this.uid;
                this.success = 'Data mahasiswa berhasil dihapus';
            }
            _handleDelete(e) {
                this.method = 'GET';
                this.url = '/api/mahasiswa';
                this.set('response', e.detail.response);
            }
        }

        window.customElements.define(FormDelete.is, FormDelete);
    </script>
</dom-module>
form-edit.html
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/paper-button/paper-button.html">
<link rel="import" href="../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../bower_components/iron-input/iron-input.html">
<link rel="import" href="../shared-styles.html">

<dom-module id="form-edit">
    <template>
        <style include="shared-styles">
            :host {
                display: block;

                padding: 10px;
            }
        </style>

        <h2>Ubah Data Mahasiswa</h2>
        <input type="hidden" value="{{formData.id::input}}">
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.npm::input}}" placeholder="Npm">
            </iron-input>
        </paper-input-container>
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.nama::input}}" placeholder="Nama">
            </iron-input>
        </paper-input-container>
        <paper-input-container>
            <iron-input slot="input">
                <input type="text" value="{{formData.kelas::input}}" placeholder="Kelas">
            </iron-input>
        </paper-input-container>

        <div class="buttons">
            <paper-button raised class="link" on-click="editMahasiswa" style="margin-top: 20px;" dialog-confirm>Ubah Data
            </paper-button>
        </div>

        <iron-ajax auto id="getMahasiswaAjax" url="{{mhsurl}}" method="GET" handle-as="json"
            content-type="application/json" on-response="_handleGet">
            </iron-ajax>
            <iron-ajax auto id="editMahasiswaAjax" url="{{url}}" method="{{method}}" handle-as="text"
                content-type="application/json" on-response="_handleUpdate">
                </iron-ajax>
    </template>

    <script>
        class FormEdit extends Polymer.Element {
            static get is() { return 'form-edit'; }

            static get properties() {
                return {
                    formData: {
                        type: Object,
                        value: function () {
                            return { id: 0, npm: '', nama: '', kelas: '' }
                        }
                    },
                    url: String,
                    mhsurl: {
                        computed: '_computeUrl(uid)'
                    },
                    method: String,
                    success: {
                        type: String,
                        notify: true
                    },
                    response: {
                        type: Object,
                        notify: true
                    },
                    uid: Number,
                }
            }

            _computeUrl(uid) {
                return ['/api/mahasiswa', uid].join('/');
            }

            editMahasiswa() {
                this.url = '/api/mahasiswa';
                this.method = 'PUT';
                this.success = 'Data mahasiswa berhasil diubah';
                this.$.editMahasiswaAjax.params = this.formData;
                this.formData = {};
            }

            _handleUpdate(e) {
                this.method = 'GET';
                this.set('response', JSON.parse(e.detail.response));
            }
            _handleGet(e) {
                this.set('formData', e.detail.response.data);
            }

        }

        window.customElements.define(FormEdit.is, FormEdit);
    </script>
</dom-module>