r17 - 23 May 2007 - 12:18:10 - ThanapolWisuttikulYou are here: SETEC Wiki >  Knowledge Web  > WebTechnologyCategory > RubyOnRails > CodingOnRails > RubyOnRailsCourse3 > ECommerceOnRuby4
-- CharinyaKlakhang - 22 May 2012 - 13:52

การสร้าง application E-commerce part 4

บทที่ 6 : Administrivia

บทนี้เป็นบทสุดท้ายของการสร้าง Application Ecommerce ที่ผ่านมาจะเห็นได้ว่าทุกคนสามารถเข้ามาดำเนินการ และแก้ไข เปลี่ยนแปลงข้อมูล ในโปรแกรมได้ โดยไม่ต้องมี User และ Password ซึ่งยังถือว่าเป็นระบบที่ไม่สมบูรณ์


login3.png

1. Run InstantRails
2. สร้างตารางชื่อ users
3. สร้าง Admin users 
   3.1 สร้าง model ชื่อ User
   3.2 สร้าง controller ชื่อ Login
   3.3 แก้ไข Login_controller.rb , สร้างเมธอด add_user()
   3.4 แก้ไข views ชื่อ add_user.rhtml
4. สร้าง password
   4.1 แก้ไข model ชื่อ user.rb
5. ตรวจสอบการกรอกข้อมูล
6. สร้างหน้าจอการ Login
   6.1 แก้ไข login_controller.rb , เพิ่มเมธอดชื่อ login()
   6.2 แก้ไข models ชื่อ user.rb
   6.3 แก้ไข views ชื่อ login.rhtml
7. สร้าง Homepage ของ admin
   7.1 ปรับแต่งเมนูด้านข้าง  แก้ไข layouts ขื่อ admin.rhtml
   7.1 แก้ไข login_controller.rb ,เพิ่มเมธอด index()
   7.2 แก้ไข views ชื่อ index.rhtml
   7.3 แก้ไข models ชื่อ order.rb
8. ป้องกันการเข้าถึงเว็บ ส่วน admin
   8.1 แก้ไข appplication.rb
   8.2 แก้ไข admin_controller.rb
   8.3 แก้ไข login_controller.rb
9. ปรับแต่งการแสดงผล
   8.1 แก้ไข login_controller.rb
10. แสดงรายชื่อ admin users
   10.1 แก้ไข login_controller.rb , เพิ่มเมธอด list_users()
   10.2 แก้ไข views ชื่อ list_users.rhtml
11. ลบรายชื่อ admin users
   11.1 แก้ไข login_controller.rb ,เพิ่มเมธอด delete_user()
12. สร้างการ Logout
   12.1 แก้ไข login_controler.rb เพิ่มเมธอด logout()


เราต้องให้ทุกคนที่เข้ามาใช้งานต้องเข้าสู่ฟังก์ชัน Administrative ก่อน ดังนั้นเราต้องมีตารางเก็บข้อมูลของ User ที่จะใช้งาน

สร้างตารางชื่อ users

  • ดังคำสั่ง sql นี้

create table users (
  id              int           not null auto_increment,
  name        varchar(100)  not null,
  hashed_password char(40)      null,
  primary key (id)
);

ecom2_new_product96.png


สร้าง Admin users

เมื่อสร้างตาราง users เราต้องสร้าง Model ด้วย

สร้าง model ชื่อ User

ecom2_new_product97.png

 > cd ecommerce
 > ruby script/generate model User


สร้าง controller ชื่อ Login

 > ruby script/generate controller Login add_user login logout delete_user list_users

ecom2_new_product98.png

จะเห็นได้ว่า มีการกำหนด action ต่างๆ ให้กับ controller Login (add_user login logout delete_user list_users)

ecom2_new_product99.png


แก้ไข Login_controller.rb , สร้างเมธอด add_user()

ดังนั้นเราจึงไปกำหนดการทำงานให้ action ดังต่อไปนี้

Action : add_user

def add_user
    if request.get?
      @user = User.new
    else
      @user = User.new(params[:user])
      if @user.save
        flash[:notice] = "User #{@user.name} created"
        redirect_to :action => 'index'
      end
    end
end

ecom2_new_product101.png

อธิบาย code ใน action : add_user

  • ใน method : add_user() จะสร้าง User สมาชิกในการซื้อสินค้าใน Web site
  • มีการตรวจสอบ ว่า form มีข้อมูลหรือไม่ ถ้าไ่ม่มีจะหมายถึงส่งข้อมูลแบบ get แต่ถ้ามีจะเป็นแบบ post
  • ถ้าเป็นแบบ get จะไม่มีการสร้าง user แต่ post จะสร้าง user โดยนำข้อมูลใน form มาจัดเก็บลง datatbase และลิงค์ไปที่หน้า index


ต่อไปเราจะสร้าง form ให้กรอกข้อมูล สำหรับการ add_user จึงต้องสร้าง View : add_user.rhtml

แก้ไข views ชื่อ add_user.rhtml

สร้าง template add_user.rhtml ที่ path : app/views/login/add_user.rhtml ดังนี้

ecom2_new_product102.png

ecom2_new_product103.png

<% @page_title = "Add User" -%>
<%= error_messages_for 'user' %>

<%= form_tag %>

<table>
  <tr>
    <td>User name:</td>
    <td><%= text_field("user", "name") %></td>
  </tr>
  <tr>
    <td>Password:</td>
    <td><%= password_field("user", "password") %></td>
  </tr>

  <tr>
    <td></td>
    <td><input type="submit" value=" ADD USER " /></td>
  </tr>
</table>

<%= end_form_tag %>


สร้าง password

ในฐานข้อมูล users จะมี field ของ hased password(ไม่ใช่ password) จะเก็บ password ในรูปแบบของ hashed string เพื่อป้องกันข้อมูลที่เป็นความลับ

สังเกตว่าใน form จะรับข้อมูลมาในรูปแบบของ plain text (form ทั่วๆไป) ดังนั้น Model : user ต้องมีหน้าที่เปลี่ยนข้อมูล password ในรูปแบบ hashed password ก่อนเขียนลง database

เพราะว่า Class : User ใน Active Record Model รู้ว่าในตาราง Users มี filed : hashed_password แต่ไม่มี field : password (plain text) ดังนั้น เราต้องเขียนโปรแกรมเปลี่ยนข้อมูลที่รับจาก form (password) เป็น string ที่ถูก hashed เป็น hashed_password

จึงต้องกำหนด การเข้าถึง field ในตาราง โดยใน Ruby จะใช้ attr_accessor

class User < ActiveRecord::Base
  attr_accessor :password

เราต้องแน่ใจได้ว่า hased password ได้ถูก set ค่าจาก attribute password (plain text) ก่อนที่จะถูก model จัดเก็บลง database เราสามารถใช้ hook facility เขียนใน ActiveRecord?

Active Record จะเขียน Callback hook สำหรับการทำงานเหล่านี้ เช่น ก่อน model จะถูกตรวจสอบ(validate) , ก่อนที่ rows จะถูก save , หลังจากสร้าง row ใหม่ เป็นต้น แต่ในที่นี้จะใช้ before callback และ after callback สำหรับจัดการ password

ก่อนที่ user row จะถูก save เราจะใช้ before_create() hook นำ plain text password มาเข้า SHA1 hash function และเก็บผลลัพธ์ใน attribute : hashed_password ซึ่งนั่นก็หมายความว่าคอลัมภ์ hashed_password ใน database ได้ถูก set ค่าในรูปแบบของ hashed value ก่อนที่ model จะเขียนลงไป

หลังที่ user row ถูก save เราจะใช้ affter_create() hook เคลียร์ค่า field plain text password ให้ว่าง เพราะว่า Object : user จะเก็บค่าเหล่านี้ไว้ใน session ดังนั้นเราต้องเคลียร์ค่า


แก้ไข model ชื่อ user.rb

เราสามารถเขียน code สำหรับจัดการ password ได้ดังนี้

  • ที่ path : app/models/user.rb

require "digest/sha1"

class User < ActiveRecord::Base

  attr_accessor :password
  attr_accessible :name, :password
  
  def before_create
    self.hashed_password = User.hash_password(self.password)
  end
  def after_create
    @password = nil
  end
  private
  def self.hash_password(password)
    Digest::SHA1.hexdigest(password)
  end
end

ecom2_new_product104.png


ตรวจสอบการกรอกข้อมูล

เพิ่ม validation สำหรับตรวจสอบข้อมูลใน form ที่ไฟล์นี้อีก 2 บรรทัด

  validates_uniqueness_of :name
  validates_presence_of   :name, :password

  • validates_uniqueness_of : ตรวจสอบว่าข้อมูลห้ามซ้ำ
  • validates_presence_of : ตรวจสอบว่าจะต้องกรอกเสมอ

ecom2_new_product105.png


ขณะนี้เราสามารถเพิ่ม user(add user) ใน database ของเราได้แล้ว

เรียกไปที่ URL : http://127.0.0.1:3000/login/add_user จะเห็นหน้าจอดังนี้

ecom2_new_product106.png

ecom2_new_product107.png

เมื่อไปเปิดดูใน databse จะได้ผลดังนี้

ecom2_new_product108.png


สร้างหน้าจอการ Login

ในที่นี้ หมายถึงการสร้าง form การ Login สำหรับ admin เพื่อจัดการกับคลังสินค้า สิ่งที่ต้องมี

  • form ที่ต้องกรอก user , password
  • จัดเก็บการ login ในรูปแบบ session ตลอดการทำงาน จนกระทั่งมีการ logout
  • ป้องกันการเข้าถึงหน้า web page admin ทาง URL (โดยการพิมพ์เรียกมาทาง URL) ซึ่งจะอนุญาติให้ผู้ที่เข้าหน้า web page นี้ได้เฉพาะ administrater เท่านั้น


แก้ไข login_controller.rb , เพิ่มเมธอดชื่อ login()

เราต้องใช้ action:login() ใน controller:login และเก็บการ login ใน session ของ administrator โดยมีการเก็บ id ของ Object : user โดยใช้ :user_id โดยมีการเขียน code ที่ path : app/controllers/login_controller.rb ดังนี้

def login
    if request.get?
      session[:user_id] = nil
      @user = User.new
    else
      @user = User.new(params[:user])
      logged_in_user = @user.try_to_login

      if logged_in_user
        session[:user_id] = logged_in_user.id
        redirect_to(:action => "index")
      else
        flash[:notice] = "Invalid user/password combination"
      end
    end
end

ecom2_new_product109.png

อธิบาย code ดังนี้

  • code นี้ก็ใช้เทคนิคเดียวกันกับ method : add_user()
  • มีการใ้ช้ request และ response ใน method เดียวกัน
  • ใน Get จะกำหนดให้สร้าง Object : User เพื่อเตรียมข้อมูล default ของ form
  • เราจะเคลียร์ session ของ user path ถ้าไม่มีการ login ที่ถูกต้อง

  • ถ้า action: login ได้รับ POST data มันจะเอาข้อมูลไปเก็บไว้ใน object : user
  • ใน code นี้ Object จะมีการเรียกใช้ method try_to_login() ที่จะคืนค่าออกมาเป็น Object : User ที่ได้มาจาก rows ใน database ที่มีชื่อ name และ hashed password ตรง ซึ่งใน model : user.rb ต้องมีการเขียน code ดังนี้


แก้ไข models ชื่อ user.rb

เขียนที่ path : app/models/user.rb

def self.login(name, password)
    hashed_password = hash_password(password || "")
    find(:first,
         :conditions => ["name = ? and hashed_password = ?", 
                          name, hashed_password])
end
def try_to_login
    User.login(self.name, self.password)
end

ecom2_new_product110.png

อธิบาย code ดังนี้

  • เมื่อมีการเรียกใช้ @user.try_to_login จาก controller เพื่อต้องการให้คืนค่าของ rows ที่มี name และ hashed_password ตรงกับ database
  • try_to_login() จึงเป็น method ที่เขียนใน Model : user.rb (ติดต่อกับตาราง users) เพื่อดึง row ที่ต้องการออกมาส่งกลับคืนไปให้ controller ซึ่งรอรับค่าอยู่
  • ภายในมีการเรียกใช้ method : login ต่อเพื่อ นำค่า plain text password มาเข้า ฟังก์ชั่น hash_password เพื่อ hash ข้อมูล ก่อนที่จะใช้ method find() สำหรับดึง row ที่มี name และ hashed_password ตรงกับค่านี้
  • สรุปการทำงานไป-กลับ ดังนี้

controller  ---> try_to_login() ---> login() --->find() 
controller  <--- try_to_login() <--- login() <--- find()      return a row


แก้ไข views ชื่อ login.rhtml

เราต้องสร้างหน้าของ login (View) ใน login.rhtml ซึ่ง code จะคล้ายกับ view : add_user ดังนี้

เขียนที่ path : app/views/login/login.rhtml

<% @page_title = "Login" -%>
<%= error_messages_for 'user' %>

<%= form_tag %>
<table>
  <tr>
    <td>User name:</td>
    <td><%= text_field("user", "name") %></td>
  </tr>
  <tr>
    <td>Password:</td>
    <td><%= password_field("user", "password") %></td>
  </tr>

  <tr>
    <td></td>
    <td><input type="submit" value=" LOGIN " /></td>
  </tr>
</table>

<%= end_form_tag %>

ecom2_new_product111.png


ปรับแต่งเมนูด้านข้าง

จะเห็นได้ว่ามีการเพิ่มฟังก์ชันให้กับ administor ดังเช่น add_user(),list_users(),delete_user(),logout ขึ้นมา ดังนั้นเราต้องสร้างเมนูเพื่อลิงค์ไปยังการทำงานเหล่านี้

ในที่นี้เราจะเขียนเมนู Sidebar ใน layout ของ admin.rhtml เพื่อจัดรูปแบบให้มีความเหมาะสมมากขึ้น

แก้ไข layouts ขื่อ admin.rhtml

โดยการแก้ไขไฟล์ admin.rhtml ที่ part : app/views/layouts/admin.rhtml ดังนี้

<html>
    <head>
        <title>Admin: <%= controller.action_name %></title>
        <%= stylesheet_link_tag "scaffold","catalog","admin", :media => "all" %>
    </head>
    <body>
        <div id="banner">
            <%= @page_title || "Admin management" %>
        </div>
        <div id="columns">
            <div id="side">
              <% if session[:user_id] -%>   
              <%= link_to("Products",   :controller => "admin", :action => "list") %><br />
              <%= link_to("Shipping",   :controller => "admin", :action => "ship") %><br /><br />

         <%= link_to("Add user", :controller => "login", :action => "add_user") %><br />
              <%= link_to("List users", :controller => "login", :action => "list_users") %><br /><br />

         <%= link_to("Log out", :controller => "login", :action => "login") %><br />          
              <%= link_to("Web shopping",   :controller => "store", :action => "index") %><br />
                       <% end -%>
             <br />
            </div>
       
      <div id="main">
  
          <% if flash[:notice] -%>
              <div id="notice"><%= flash[:notice] %></div>
          <% end -%>
     <br /> 
          <%= @content_for_layout %>
       <br /> <br /> <br /><br /><br />
      </div>
    </div>
     
  </body>
</html>
  </body>
</html>

ecom2_new_product127.png

ecom2_new_product129.png

สร้าง Homepage ของ admin

แก้ไข login_controller.rb ,เพิ่มเมธอด index()

เขียน action : index() ใน part : app/controllers/login_controller.rb ดังนี้

def index
    @total_orders = Order.count
    @pending_orders = Order.count_pending
end

ecom2_new_product114.png

แก้ไข views ชื่อ index.rhtml

สุดท้าย เราจะสร้างหน้า index ของ controller : login นี้ ที่ part : app/views/login/index.rhtml ดังนี้

<%  @page_title = "Administer E-commerce" -%>
<h1>E-commerce Store Status</h1>
<p>
  Total orders in system: <%= @total_orders %>
</p>
<p>
  Orders pending shipping: <%= @pending_orders %>
</p>

ecom2_new_product112.png

ecom2_new_product113.png


แก้ไข models ชื่อ order.rb

เขียน method class ใน Model : order เพื่อ return จำนวนตัวเลขของ pending orders หรือ จำนวน order สินค้าที่ยังไม่ได้ส่งไปให้ลูกค้า ดังนี้

ที่ part : app/models/order.rb

def self.count_pending
    count("shipped_at is null")
end

ecom2_new_product115.png


ขณะนี้ เรามีส่วนของการ login แล้ว โดยทดสอบที่ URL : http://127.0.0.1:3000/login/login

ecom2_new_product116.png

ถ้า user และ password ถูกต้อง จะทำการ redirect ไปยังหน้า index()

ecom2_new_product117.png


ป้องกันการเข้าถึงเว็บ ส่วน admin (Limiting Access)

เราป้องกันไม่ให้บุคคลที่ไม่ใช่ Administor เข้าหน้าของ admin โดยการใช้ Rails filter

Rails filter จะป้องกัน user เรียกไปที่ action method โดยไม่ต้อง login ดังนั้นควรเพิ่มกระบวนการทำงานนี้ก่อนเพื่อความปลอดภัย

ในที่นี้จะใช้ before filter ที่จะเป็นตัวป้องกันการเข้าถึงโดยการเรียกไปที่ action method ในส่วนของ controller : admin ซึ่งตัวป้องกันนี้(interceptor) สามารถตรวจสอบจาก session[user:id]

ถ้าเราตั้งค่าให้ application นี้รู้ว่า admin ต้องได้ทำการ login เข้ามาอย่างถูกต้อง จึีงอนุญาติให้ทำงานใน action ต่างๆต่อไปได ถ้าไม่ใช่จะ redirect กลับไปหน้าของ login ใหม่

เราควรวางตัว filter นี้ไว้ที่ controller : admin (เพราะเราต้องการป้องกันไม่ให้ส่วนนี้ ถูกเข้าถึงจากบุคคลอื่นที่ไม่ใช่ admin) ด้วยเหตุผลนี้เราจึงจะวางไว้ที่ ApplicationContoller ซึ่งเป็น parent class ของ controller ทุกตัวใน Application (ECommerce) นี้


แก้ไข appplication.rb

ดังนั้น เราจะเขียนในไฟล์ application.rb ที่ part: app/controllers/application.rb ดังนี้

def authorize
    unless session[:user_id]
      flash[:notice] = "Please log in"
      redirect_to(:controller => "login", :action => "login")
    end
end

ecom2_new_product118.png

Method Authorization นี้ สามารถถูกเรียกให้ทำงานก่อน action ทุกตัว ซึ่งในที่นี้เราต้องการให้มีผลต่อการจัดการกับ controller : admin โดยการเพิ่มเพียงแค่ 1 บรรทัดเท่านั้น


แก้ไข admin_controller.rb

เพิ่ม code ใน admin_controller.rb ที่ part : app/controller/admin_controller.rb ดังนี้

class AdminController < ApplicationController
  before_filter :authorize
  ...

ecom2_new_product120.png


เพียงเท่านี้การทำงานของ controller : admin จะไม่สามารถเรียก action method ได้ทาง URL แล้วจะต้อง login เป็น admin อย่างถูกต้อง จึงสามารถทำงานที่ action อื่นๆใน controller นี้ได้

และเราต้องการให้ทำงานเช่นเดียวกันที่ controller : login แต่จะอนุญาติให้ทำงานที่บาง action ได้ คือ action : login() เพราะต้องกรอกชื่อ user และ password ในหน้านี้

ecom2_new_product123.png


แก้ไข login_controller.rb

ดังนั้นเราจะเพิ่ม code ใน login_controller.rb ที่ part : app/controller/login_controller.rb

class LoginController < ApplicationController
  before_filter :authorize, :except => :login
  ...

ecom2_new_product119.png


ปรับแต่งการแสดงผลของ login

เพื่อแสดงข้อความเตือน (Error) , banner , menu side เป็นต้น

แก้ไข login_controller.rb

class LoginController < ApplicationController
  layout "admin"
  ...

ecom2_new_product122.png


เมื่อเรียกไปที่ URL: http://127.0.0.1:3000/admin หรือ action อื่นๆ ทั้งใน controller : admin และ controller : login (ยกเว้น action : login) application จะ redirect ไปที่ URL : http://127.0.0.1:3000/login/login เสมอ ดังภาพ

ecom2_new_product121.png


แสดงรายชื่อ admin users

ในที่นี้จะต้องมีการแสดง รายชื่อ admin ทั้งหมดที่เราได้ทำการ add user เอาไว้ โดยการเพิ่ม code ดังนี้

แก้ไข login_controller.rb , เพิ่มเมธอด list_users()

def list_users
    @all_users = User.find(:all)
end

ecom2_new_product124.png


แก้ไข views ชื่อ list_users.rhtml

<% @page_title = "User List" -%>

<table cellpadding="5" cellspacing="0" border=1 width=55%>
<tr align=center>
  <th>Name</th>
  <th>Delete</th>
</tr>

<% for user in @all_users -%>
<tr align=center>
  <td><%= user.name %></td>
  <td><%= link_to "(delete)", {:action => :delete_user, :id => user.id },:confirm => 'Are you sure?' %></td>
</tr>
<% end -%>
</table>
</table>

ecom2_new_product125.png


ลบรายชื่อ admin users

เราต้องมี function ของการลบข้อมูล user admin หาก accout นั้นไม่ได้ใช้แล้ว ในที่นี้จะลบผ่าน list_users.rhtml

แก้ไข login_controller.rb ,เพิ่มเมธอด delete_user()

def delete_user
    id = params[:id]
    if id && user = User.find(id)
      user.destroy
      flash[:notice] = "User #{user.name} deleted"
    end
    redirect_to(:action => :list_users)
end

ecom2_new_product126.png


สร้างการ Logout

เมื่อ user admin ต้องการออกจากระบบ ดังนั้น เราต้องเขียน code ที่ไฟล์ login_controller.rb

แก้ไข login_controler.rb เพิ่มเมธอด logout()

def logout
    session[:user_id] = nil
    flash[:notice] = "Logged out"
    redirect_to(:action => "login")
end

ecom2_new_product128.png


toggleopenShow attachmentstogglecloseHide attachments
Topic attachments
I Attachment Action Size Date Who Comment
pngpng ecom2_new_product96.png manage 136.2 K 19 May 2006 - 14:58 CharinyaKlakhang  
pngpng ecom2_new_product97.png manage 23.7 K 19 May 2006 - 15:40 CharinyaKlakhang  
pngpng ecom2_new_product98.png manage 162.9 K 19 May 2006 - 15:41 CharinyaKlakhang  
pngpng ecom2_new_product99.png manage 27.0 K 19 May 2006 - 15:41 CharinyaKlakhang  
pngpng ecom2_new_product100.png manage 23.0 K 19 May 2006 - 15:41 CharinyaKlakhang  
pngpng ecom2_new_product101.png manage 24.0 K 22 May 2006 - 09:32 CharinyaKlakhang  
pngpng ecom2_new_product102.png manage 23.2 K 22 May 2006 - 09:43 CharinyaKlakhang  
pngpng ecom2_new_product103.png manage 28.1 K 22 May 2006 - 09:43 CharinyaKlakhang  
pngpng ecom2_new_product104.png manage 26.4 K 22 May 2006 - 11:04 CharinyaKlakhang  
pngpng ecom2_new_product105.png manage 27.8 K 22 May 2006 - 11:04 CharinyaKlakhang  
pngpng ecom2_new_product107.png manage 17.9 K 22 May 2006 - 11:16 CharinyaKlakhang  
pngpng ecom2_new_product108.png manage 14.0 K 22 May 2006 - 11:16 CharinyaKlakhang  
pngpng ecom2_new_product106.png manage 19.6 K 22 May 2006 - 11:17 CharinyaKlakhang  
pngpng ecom2_new_product109.png manage 37.1 K 22 May 2006 - 15:22 CharinyaKlakhang  
pngpng ecom2_new_product110.png manage 24.7 K 22 May 2006 - 16:57 CharinyaKlakhang  
pngpng ecom2_new_product111.png manage 28.4 K 22 May 2006 - 17:46 CharinyaKlakhang  
pngpng ecom2_new_product112.png manage 18.3 K 22 May 2006 - 17:46 CharinyaKlakhang  
pngpng ecom2_new_product113.png manage 26.1 K 22 May 2006 - 17:46 CharinyaKlakhang  
pngpng ecom2_new_product116.png manage 20.7 K 22 May 2006 - 18:11 CharinyaKlakhang  
pngpng ecom2_new_product117.png manage 25.7 K 22 May 2006 - 18:12 CharinyaKlakhang  
pngpng ecom2_new_product114.png manage 30.5 K 22 May 2006 - 18:13 CharinyaKlakhang  
pngpng ecom2_new_product115.png manage 133.0 K 22 May 2006 - 18:13 CharinyaKlakhang  
pngpng ecom2_new_product118.png manage 89.2 K 23 May 2006 - 10:30 CharinyaKlakhang  
pngpng ecom2_new_product119.png manage 23.9 K 23 May 2006 - 10:30 CharinyaKlakhang  
pngpng ecom2_new_product120.png manage 27.0 K 23 May 2006 - 10:30 CharinyaKlakhang  
pngpng ecom2_new_product122.png manage 30.1 K 23 May 2006 - 11:03 CharinyaKlakhang  
pngpng ecom2_new_product121.png manage 30.5 K 23 May 2006 - 11:03 CharinyaKlakhang  
pngpng ecom2_new_product123.png manage 19.9 K 23 May 2006 - 11:07 CharinyaKlakhang  
pngpng ecom2_new_product126.png manage 26.0 K 23 May 2006 - 11:51 CharinyaKlakhang  
pngpng ecom2_new_product125.png manage 67.5 K 23 May 2006 - 11:51 CharinyaKlakhang  
pngpng ecom2_new_product124.png manage 22.5 K 23 May 2006 - 11:51 CharinyaKlakhang  
pngpng ecom2_new_product127.png manage 95.3 K 23 May 2006 - 13:53 CharinyaKlakhang  
pngpng ecom2_new_product128.png manage 18.5 K 23 May 2006 - 14:12 CharinyaKlakhang  
pngpng ecom2_new_product129.png manage 27.6 K 23 May 2006 - 16:07 CharinyaKlakhang  
Edit | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r17 < r16 < r15 < r14 < r13 | More topic actions
 
Powered by SETEC Wiki
Copyright ©2012 by National Electronics and Computer Technology Center, NECTEC.
Ideas, requests, problems regarding SETEC Wiki? Send feedback