View · Index

Weblog

Showing 111 - 120 of 696 Postings (summary)

::xo::db Object Relational Database Interface

Created by Gustaf Neumann, last modified by Antonio Pisano 26 Jun 2018, at 06:01 PM

The database abstraction layer of xotcl-core interfaces between the OpenACS object model used in the relational Database and XOTcl objects. The database abstraction layer works for PostgreSQL and Oracle in exact the same way.

The functionality of the database abstraction layer provides separate classes for operation on generic ACS objects and on objects stored in the OpenACS content repository. The generic lookup queries and instantiate methods are provided through the following classes

Generic operations on ACS Object IDs:

  • ::xo::db::Class get_object_type -id
  • ::xo::db::Class get_instance_from_db -id
  • ::xo::db::Class exists_in_db -id
  • ::xo::db::Class delete -id

Generic operations on ACS Object Types:

  • ::xo::db::Class get_table_name -object_type
  • ::xo::db::Class object_type_exists_in_db -object_type
  • ::xo::db::Class get_class_from_db -object_type
  • ::xo::db::Class drop_type -object_type -drop_table -cascade_p
  • ::xo::db::Class delete_all_acs_objects -object_type

Generic operations on items of the content repository:

  • ::xo::db::CrClass get_object_type -item_id -revision_id
  • ::xo::db::CrClass get_instance_from_db -item_id -revision_id
  • ::xo::db::CrClass lookup -item_id -revision_id
  • ::xo::db::CrClass delete -item_id

Methods on classes for ACS Object Types

  • <classname> new_persistent_object -package_id -creation_user -creation_ip ...
  • <classname> object_types -subtypes_first
  • <classname> create_object_type
  • <classname> drop_object_type -cascade
  • <classname> instance_select_query ...
  • <classname> get_instances_from_db ...

Methods on content repository classes

  • <classname> new_persistent_object -package_id -creation_user -creation_ip ...
  • <classname> create_object_type
  • <classname> drop_object_type
  • <classname> get_instance_from_db -item_id -revision_id
  • <classname> instance_select_query ...
  • <classname> get_instances_from_db ...
  • <classname> folder_type_unregister_all -include_subtypes -folderid register|unregister
  • <classname> folder_type_unregister_all -include_subtypes

Methods on instances of ordinary classes

  • <object> save -package_id -modifying_user
  • <object> save_new -package_id -creation_user -creation_ip
  • <object> delete

Methods on instances of content repository classes

  • <object> save -modifying_user -live_p
  • <object> save_new -package_id -creation_user -creation_ip -live_p
  • <object> set_live_revision -revision_id -publish_status
  • <object> delete

The following links provide a detailed description of these classes in the version as they are installed on openacs.org: ::xo::db::Class and ::xo::db::CrClass

The xotcl-core Database Abstraction Layer by Examples 

The remainder of this page provides a short tutorial into the basic functionality of the interface. A more detailed description can be found in the xotcl-core tutorial

############################################################
#
# 1) Create new ACS Objects, destroy it in memory, 
#    load it from the database, delete it in the database.
#
.. Create a plain new ACS object just for demo purposes.
.. The ACS object is created with a new object id.

>> set o [::xo::db::Object new_persistent_object]
=  ::7845

.. Show the contents of object ::7845 by serializing it:

>> ::7845 serialize
=  ::xo::db::Object create ::7845 -noinit \
    -set object_title {Object 7845} \
    -set object_id 7845 


.. In the next steps, we (a) get the object_id of the newly
.. created ACS object, (b) destroy the XOTcl object (the ACS
.. object is still in the database, (c) we recreate the
.. XOTcl object from the database, and (d) delete it in the 
.. database.

.. Step (a)
>> set o_id [::7845 object_id]
=  7845

#
# Delete object from memory: <object> destroy 
# Check, if an XOTcl object exists: ::xotcl::Object isobject <obj>
#
>> ::xotcl::Object isobject ::7845
=  1

.. Step (b)
>> ::7845 destroy

>> ::xotcl::Object isobject ::7845
=  0

#
# Load an object from the database: ::xo::db::Class get_instance_from_db -id <id>
#
.. Step (c)
>> set o [::xo::db::Class get_instance_from_db -id 7845]
=  ::7845

>> ::xotcl::Object isobject ::7845
=  1

.. Now, we have recreated the same object as before:

>> ::7845 serialize
=  ::xo::db::Object create ::7845 -noinit \
    -set object_title {Object 7845} \
    -set object_id 7845 


#
# Check, if an ACS object exists in the database: ::xo::db::Class exists_in_db -id <id>
# Delete object from memory and database: <object> delete 
#
>> ::xo::db::Class exists_in_db -id 7845
=  1

.. Step (d)
>> ::7845 delete

.. Now, we have deleted the ACS Object and the XOTcl object:

>> ::xo::db::Class exists_in_db -id 7845
=  0

>> ::xotcl::Object isobject ::7845
=  0


############################################################
#
# 2) Create new ACS Object Types, ACS Attributes and 
#    SQL Tables from XOTcl Classes with slot definitions.
#
.. We want to create a new ACS Object type and 
.. an XOTcl class named ::demo::Person.

.. Does the ACS Object type ::demo::Person exist in the database?
>> ::xo::db::Class object_type_exists_in_db -object_type ::demo::Person
=  0

.. The ACS Object Type should not exist (statement should return 0)

.. We create a new XOTcl Class '::demo::Person'.
.. By defining this class, the database layer takes care
.. of creating the ACS Object Type and the necessary table via SQL.

.. The persistent attributes (stored in the database) are defined
.. as slots of type ::xo::db::Attribute.

>> 
::xo::db::Class create ::demo::Person  \
   -superclass ::xo::db::Object  \
   -slots {
      ::xo::db::Attribute create name -column_name pname
      ::xo::db::Attribute create age -default 0 -datatype integer
      ::xo::db::Attribute create projects -default {} -multivalued true
    }

=  ::demo::Person

.. If the ACS Object Type and the ACS Attributes would be
.. already defined in the database, the class definition above 
.. would be a no-op operation.

.. Now, the ACS Object Type exists in the database

>> ::xo::db::Class object_type_exists_in_db -object_type ::demo::Person
=  1

.. The XOTcl class definition created automatically the 
.. following table for storing instances:

CREATE TABLE demo_person (
    age  integer DEFAULT '0' ,
    pname  text ,
    projects  text DEFAULT '' ,
    person_id  integer REFERENCES acs_objects(object_id) ON DELETE CASCADE
    CONSTRAINT demo_person_person_id_pk PRIMARY KEY 
)

.. SQL attribute slot names:
>> ::demo::Person array names db_slot
=  name age projects person_id

.. The XOTcl class definition created as well a 'save' and
.. an 'insert' method:

.. Created 'save' method:

::demo::Person instproc save {}  {
      db_transaction {
    next
    my instvar object_id name age projects
    db_dml dbqd..update_demo_person {update demo_person
      set pname = :name,age = :age,projects = :projects
          where person_id = :object_id
    }
      }
    }

.. Created 'insert' method:

::demo::Person instproc insert {}  {
      set __table_name [[self class] table_name]
      set __id [[self class] id_column]
      my set $__id [my set object_id]
      my log "ID insert in $__table_name, id = $__id = [my set $__id]"
      next
      foreach {__slot_name __slot} [[self class] array get db_slot] {
    my instvar $__slot_name
    if {[info exists $__slot_name]} { 
      lappend __vars $__slot_name
      lappend __atts [$__slot column_name]
    }
      }
      db_dml dbqd..insert_$__table_name "insert into $__table_name
        ([join $__atts ,]) values (:[join $__vars ,:])"
    }

.. The 'insert' method is typically called via
.. '<classname> new', which takes care about db_transaction (see below)

#
# Create a new instance of ::demo::Person with name 'Gustaf'
#
# The method 'new_persistent_object' of a database class (instance of ::xo::db::Class)
# creates an ACS Object with a fresh id in the database and 
# creates as well an XOTcl object in memory

>> set p [::demo::Person new_persistent_object -name Gustaf -age 105]
=  ::7846

::7846 created

.. check, if object ::7846 exists in memory
>> ::xotcl::Object isobject ::7846
=  1

.. check, if object ::7846 exists in the database
>> ::xo::db::Class exists_in_db -id 7846
=  1

.. Every persistent XOTcl object has an object_id.
>> ::7846 exists object_id
=  1

.. Show the contents of object ::7846 (using serialize)

>> ::7846 serialize
=  ::demo::Person create ::7846 -noinit \
    -set object_title {Person 7846} \
    -set name Gustaf \
    -set age 105 \
    -set projects {} \
    -set person_id 7846 \
    -set object_id 7846 


.. modify some attributes of the XOTcl object
>> ::7846 incr age
=  106

.. show modified contents of ::7846

::demo::Person create ::7846 -noinit \
    -set object_title {Person 7846} \
    -set name Gustaf \
    -set age 106 \
    -set projects {} \
    -set person_id 7846 \
    -set object_id 7846 

.. save the modified object data in the database
>> ::7846 save

>> set person_id [$p person_id]
=  7846

.. deleting xotcl object ::7846 in memory
>> $p destroy

.. check, if object ::7846 exists in memory
>> ::xotcl::Object isobject ::7846
=  0

.. check, if object ::7846 exists in the database
>> ::xo::db::Class exists_in_db -id 7846
=  1

.. fetch person again from database:

>> set p [::xo::db::Class get_instance_from_db -id 7846]
=  ::7846

.. check, if object ::7846 exists in memory
>> ::xotcl::Object isobject ::7846
=  1

::demo::Person create ::7846 -noinit \
    -set object_title {Person 7846} \
    -set name Gustaf \
    -set age 106 \
    -set projects {} \
    -set object_id 7846 \
    -set person_id 7846 


.. The object ::7846 was fetched from the database using the
.. automatically created query:

SELECT demo_person.pname AS name,demo_person.age,
   demo_person.projects,demo_person.person_id,
   acs_objects.title AS object_title,acs_objects.object_id
FROM demo_person,acs_objects
WHERE person_id = 7846 and object_id = person_id

.. In order to delete an object from the database, 
.. the method 'delete' can be used. 'delete' deletes the 
.. ACS object in the database as well the XOTcl object in memory.

>> set p_id [::7846 object_id]
=  7846

>> ::xo::db::Class exists_in_db -id 7846
=  1

>> ::7846 delete

>> ::xo::db::Class exists_in_db -id 7846
=  0

.. Instead of using 'new_persistent_object' to create
.. new acs_objects, one can use the method 'new' in 
.. combination with 'save_new'. While the method 'new' creates
.. an XOTcl object in memory, the method 'save_new' can be used
.. to create a new ACS object (with a new object_id) an to 
.. save this object persistently in the database.

>> set p [::demo::Person new -name Gustaf -age 105]
=  ::xotcl::__#A

>> ::xotcl::__#A exists object_id
=  0

>> ::xotcl::__#A save_new
=  7847

>> ::xotcl::__#A exists object_id
=  1


.. Now, we create a subclass of ::demo::Person called ::demo::Employee
.. which has a few more attributes. Again, we define an XOTcl class
.. ::demo::Employee which creates the ACS Object Type, the ACS
.. attributes and the table, if necessary.

>> 
::xo::db::Class create ::demo::Employee  \
   -superclass ::demo::Person  \
   -table_name demo_employee \
   -id_column employee_id  \
   -slots {
      ::xo::db::Attribute create salary -datatype integer
      ::xo::db::Attribute create dept_nr -datatype integer -default "0"
    }

=  ::demo::Employee


.. The XOTcl class definition created automatically the 
.. following table for storing instances:

CREATE TABLE demo_employee (
    dept_nr  integer DEFAULT '0' ,
    salary  integer ,
    employee_id  integer REFERENCES demo_person(person_id) ON DELETE CASCADE
    CONSTRAINT demo_employee_employee_id_pk PRIMARY KEY 
)

.. Create a first new employee:
>> set p1 [::demo::Employee new_persistent_object -name Neophytos -age 25]
=  ::7848

.. show contents of ::7848

::demo::Employee create ::7848 -noinit \
    -set employee_id 7848 \
    -set object_title {Employee 7848} \
    -set dept_nr 0 \
    -set name Neophytos \
    -set age 25 \
    -set projects {} \
    -set person_id 7848 \
    -set object_id 7848 

.. Create a second new employee:
>> set p2 [::demo::Employee new_persistent_object -name Lore -age 35 -salary 100000]
=  ::7849

.. show contents of ::7849

::demo::Employee create ::7849 -noinit \
    -set employee_id 7849 \
    -set object_title {Employee 7849} \
    -set salary 100000 \
    -set dept_nr 0 \
    -set name Lore \
    -set age 35 \
    -set projects {} \
    -set person_id 7849 \
    -set object_id 7849 

.. Create a third new employee:
>> set p3 [::demo::Employee new_persistent_object -name Nora -age 7 -salary 100]
=  ::7850

.. show contents of ::7850

::demo::Employee create ::7850 -noinit \
    -set employee_id 7850 \
    -set object_title {Employee 7850} \
    -set salary 100 \
    -set dept_nr 0 \
    -set name Nora \
    -set age 7 \
    -set projects {} \
    -set person_id 7850 \
    -set object_id 7850 

#
# Delete object from memory: <object> destroy 
#
>> ::xotcl::Object isobject ::7848
=  1

>> set p1_id [$p1 object_id]
=  7848

>> ::xo::db::Class exists_in_db -id 7848
=  1

>> $p1 destroy

>> ::xotcl::Object isobject ::7848
=  0

>> ::xo::db::Class exists_in_db -id 7848
=  1

#
# Delete object from memory and database: <object> delete 
#
>> ::xotcl::Object isobject ::7849
=  1

>> set p2_id [$p2 object_id]
=  7849

>> ::xo::db::Class exists_in_db -id 7849
=  1

>> $p2 delete

>> ::xotcl::Object isobject ::7849
=  0

>> ::xo::db::Class exists_in_db -id 7849
=  0

.. Fetch employee with id 7848 again from the database:

>> set p [::xo::db::Class get_instance_from_db -id 7848]
=  ::7848

.. show contents of ::7848

::demo::Employee create ::7848 -noinit \
    -set object_title {Employee 7848} \
    -set salary {} \
    -set employee_id 7848 \
    -set dept_nr 0 \
    -set name Neophytos \
    -set age 25 \
    -set projects {} \
    -set object_id 7848 \
    -set person_id 7848 

.. The object ::7848 was fetched from the database using the
.. automatically created query:

SELECT demo_employee.employee_id,demo_employee.salary,
   demo_employee.dept_nr, 
   demo_person.pname AS name,demo_person.age,
   demo_person.projects,demo_person.person_id,
   acs_objects.title AS object_title,acs_objects.object_id
FROM demo_employee,demo_person,acs_objects
WHERE employee_id = 7848 and person_id = employee_id 
   and object_id = employee_id

>> ::7848 destroy



.. Query the instances from the database

.. Instances are queried by default based on the following,
.. automatically generated SQL Query:

>> ::demo::Employee instance_select_query
=  SELECT demo_employee.employee_id,demo_employee.salary,
     demo_employee.dept_nr,
     demo_person.pname AS name,demo_person.age,
     demo_person.projects, demo_person.person_id,
     acs_objects.title AS object_title,acs_objects.object_id 
   FROM demo_employee,demo_person,acs_objects  
   WHERE person_id = employee_id and object_id = employee_id   

.. Query the object using this query into a set of objects.
>> set s [::demo::Employee get_instances_from_db]
=  ::xotcl::__#H

.. The result is an OrderedComposite. Children can be accessed
.. via the 'children' method:

>> llength [$s children]
=  2

.. serialize all children
::xotcl::Object create ::xotcl::__#I -noinit \
    -set __parent ::xotcl::__#H \
    -set object_title {Employee 7848} \
    -set dept_nr 0 \
    -set salary {} \
    -set employee_id 7848 \
    -set age 25 \
    -set name Neophytos \
    -set projects {} \
    -set object_id 7848 \
    -set person_id 7848 

::xotcl::Object create ::xotcl::__#J -noinit \
    -set __parent ::xotcl::__#H \
    -set object_title {Employee 7850} \
    -set dept_nr 0 \
    -set salary 100 \
    -set employee_id 7850 \
    -set age 7 \
    -set name Nora \
    -set projects {} \
    -set object_id 7850 \
    -set person_id 7850 

.. The instance_select_query can be configured in many ways.
.. Here we use the '-count true' option to return just the number
.. of solutions:

>> ::demo::Employee instance_select_query -count true
=  SELECT count(*) 
   FROM demo_employee,demo_person,acs_objects  
   WHERE person_id = employee_id and object_id = employee_id   

>> db_string cnt [::demo::Employee instance_select_query -count true]
=  2

.. The same queries for ::demo::Person instead of ::demo::Employee.
.. Note, that we get the person data of employees as well, since
.. employees are as well persons (i.e. a specialization of person):

>> ::demo::Person instance_select_query
=  SELECT demo_person.pname AS name,demo_person.age,
     demo_person.projects,demo_person.person_id,
     acs_objects.title AS object_title,acs_objects.object_id 
   FROM demo_person,acs_objects  
   WHERE object_id = person_id   

>> set s [::demo::Person get_instances_from_db]
=  ::xotcl::__#M

>> llength [$s children]
=  3

::xotcl::Object create ::xotcl::__#N -noinit \
    -set __parent ::xotcl::__#M \
    -set object_title {Person 7847} \
    -set age 105 \
    -set name Gustaf \
    -set projects {} \
    -set object_id 7847 \
    -set person_id 7847 

::xotcl::Object create ::xotcl::__#O -noinit \
    -set __parent ::xotcl::__#M \
    -set object_title {Employee 7848} \
    -set age 25 \
    -set name Neophytos \
    -set projects {} \
    -set object_id 7848 \
    -set person_id 7848 

::xotcl::Object create ::xotcl::__#P -noinit \
    -set __parent ::xotcl::__#M \
    -set object_title {Employee 7850} \
    -set age 7 \
    -set name Nora \
    -set projects {} \
    -set object_id 7850 \
    -set person_id 7850 

TODO: explain more options for instance_select_query and get_instances_from_db

############################################################
#
# 3) Create XOTcl classes from existing ACS Object Types
#    and ACS Attributes based on the definitions in the
#    database

>> set c [::xo::db::Class get_class_from_db -object_type party]
=  ::xo::db::party

.. XOTcl class ::xo::db::party created (superclass ::xo::db::Object)
.. SQL attributes:
>> ::xo::db::party array names db_slot
=  email party_id url

>> set c [::xo::db::Class get_class_from_db -object_type person]
=  ::xo::db::person

.. XOTcl class ::xo::db::person created (superclass ::xo::db::party)
.. SQL attributes:
>> ::xo::db::person array names db_slot
=  last_name first_names person_id

>> set c [::xo::db::Class get_class_from_db -object_type user]
=  ::xo::db::user

.. XOTcl class ::xo::db::user created (superclass ::xo::db::person)
.. SQL attributes:
>> ::xo::db::user array names db_slot
=  user_id

>> set c [::xo::db::Class get_class_from_db -object_type group]
=  ::xo::db::group

.. XOTcl class ::xo::db::group created (superclass ::xo::db::party)
.. SQL attributes:
>> ::xo::db::group array names db_slot
=  group_name group_id

.. Create XOTcl object for user_id = 0

.. please log in
>> set u [::xo::db::Class get_instance_from_db -id $myuser]
=  ::0

.. ::0 created, class ::xo::db::user
.. class hierarchy for ::0 ::xo::db::user ::xo::db::person ::xo::db::party ::xo::db::Object ::xotcl::Object
.. show contents of ::0

::xo::db::user create ::0 -noinit \
    -set object_title Unregistered Visitor \
    -set party_id 0 \
    -set email {} \
    -set last_name Visitor \
    -set object_id 0 \
    -set url {} \
    -set person_id 0 \
    -set first_names Unregistered \
    -set user_id 0 

.. The object ::0 was fetched from the database using the
.. automatically created query:

SELECT users.user_id,persons.last_name,persons.first_names,
  persons.person_id,parties.email,
  parties.party_id,parties.url,
  acs_objects.title AS object_title,acs_objects.object_id
FROM users,persons,parties,acs_objects
WHERE user_id = 0 and person_id = user_id and 
  party_id = user_id and object_id = user_id

.. Now we modify the user. To be on the safe side, we
.. a) save firstly the original URL of the current user, then
.. b) we set it to a new value and save the user information
..    to the database
.. c) delete the user object in memory
.. d) load it again from the database to see the modified data
.. e) reset it to the original value and save it again to restore
..    the original state

.. Step a:
>> set url [::0 url]

.. Step b:
>> ::0 url https://openacs.org/
=  https://openacs.org/

>> ::0 save

.. Step c:
>> ::0 destroy

.. Step d:
>> set u [::xo::db::Class get_instance_from_db -id $myuser]
=  ::0

.. show contents of ::0

::xo::db::user create ::0 -noinit \
    -set object_title Unregistered Visitor \
    -set party_id 0 \
    -set email {} \
    -set last_name Visitor \
    -set object_id 0 \
    -set url https://openacs.org" \
    -set person_id 0 \
    -set first_names Unregistered \
    -set user_id 0 

.. Step e:
>> ::0 url $url

>> ::0 save

>> ::0 destroy

>> set u [::xo::db::Class get_instance_from_db -id $myuser]
=  ::0

.. show contents of ::0

::xo::db::user create ::0 -noinit \
    -set object_title Unregistered Visitor \
    -set party_id 0 \
    -set email {} \
    -set last_name Visitor \
    -set object_id 0 \
    -set url {} \
    -set person_id 0 \
    -set first_names Unregistered \
    -set user_id 0 



############################################################
#
# 4) Use the generic Content Repository interface (using 
#    just cr_items and cr_revisions)
#

.. check, if cr_item with name 'testing' exists
>> set item_id [::xo::db::CrClass lookup -name testing]
=  7841

.. yes, it exists; delete it without instantiating
>> ::xo::db::CrItem delete -item_id 7841

.. create item
>> set i [::xo::db::CrItem new  -name "testing"  -title "Title of Hello World"  -text "Hello World"  ]
=  ::xotcl::__#a

>> $i save_new
=  7852

.. show contents of item

::xo::db::CrItem create ::xotcl::__#a -noinit \
    -set creation_date {2007-09-03 23:28:26.727511+02} \
    -set creation_user 0 \
    -set object_id 7852 \
    -set description {} \
    -set text {Hello World} \
    -set nls_language en_US \
    -set mime_type text/plain \
    -set name testing \
    -set publish_status ready \
    -set title {Title of Hello World} \
    -set revision_id 7851 \
    -set item_id 7852 \
    -set last_modified {2007-09-03 23:28:26.727511+02} \
    -set parent_id -100 

.. update content

>> ::xotcl::__#a append text {... more text.. more text.. more text.}
=  Hello World... more text.. more text.. more text.

>> ::xotcl::__#a append title { - v2}
=  Title of Hello World - v2

.. show modified contents of item

::xo::db::CrItem create ::xotcl::__#a -noinit \
    -set creation_date {2007-09-03 23:28:26.727511+02} \
    -set creation_user 0 \
    -set object_id 7852 \
    -set description {} \
    -set text {Hello World... more text.. more text.. more text.} \
    -set nls_language en_US \
    -set mime_type text/plain \
    -set name testing \
    -set publish_status ready \
    -set title {Title of Hello World - v2} \
    -set revision_id 7851 \
    -set item_id 7852 \
    -set last_modified {2007-09-03 23:28:26.727511+02} \
    -set parent_id -100 

>> ::xotcl::__#a save
=  7852

.. method 'save' creates a new revision; see changed revision_id below

::xo::db::CrItem create ::xotcl::__#a -noinit \
    -set creation_date {2007-09-03 23:28:26.727511+02} \
    -set creation_user 0 \
    -set object_id 7852 \
    -set description {} \
    -set text {Hello World... more text.. more text.. more text.} \
    -set nls_language en_US \
    -set mime_type text/plain \
    -set name testing \
    -set publish_status ready \
    -set title {Title of Hello World - v2} \
    -set revision_id 7853 \
    -set item_id 7852 \
    -set last_modified {2007-09-03 23:28:26.727511+02} \
    -set parent_id -100 

>> set item_id 7852
=  7852

>> ::xotcl::__#a destroy

>> set i [::xo::db::CrClass get_instance_from_db -item_id 7852]
=  ::7852

::xo::db::CrItem create ::7852 -noinit \
    -set object_type content_revision \
    -set creation_date {2007-09-03 23:28:26.727511+02} \
    -set object_id 7853 \
    -set creation_user 0 \
    -set description {} \
    -set text {Hello World... more text.. more text.. more text.} \
    -set nls_language en_US \
    -set package_id 492 \
    -set name testing \
    -set mime_type text/plain \
    -set publish_status ready \
    -set title {Title of Hello World - v2} \
    -set item_id 7852 \
    -set revision_id 7853 \
    -set last_modified {2007-09-03 23:28:26.750059+02} \
    -set parent_id -100 

############################################################
#
# 5) Create new application classes by sub-typing the 
#    Content Repository, adding additional attributes
#

.. We create a subclass of ::xo::db::CrItem called ::demo::Page
.. which has a few more attributes. Actually, this class is very
.. similar to ::xowiki::Page. Again, we define an XOTcl class
.. ::demo::Page which creates the ACS Object Type, the ACS
.. attributes and the table, if necessary.

>> 
  # content class very similar to ::xowiki::Page
  ::xo::db::CrClass create Page \
    -superclass ::xo::db::CrItem  \
    -pretty_name "demo Page"  \
    -mime_type text/html  \
    -slots {
        if {[::xo::db::has_ltree]} {
          ::xo::db::CrAttribute create page_order \
            -sqltype ltree -validator page_order \
            -default ""
        }
        ::xo::db::CrAttribute create creator \
            -column_name creator_string
      }

=  ::demo::Page

.. The sql_attribute_names for content items contain
.. the attributes of all supertypes:

>> ::demo::Page array names db_slot
=  creator page_order page_id object_id description text object_title nls_language mime_type name title item_id revision_id

>> ::demo::Page info slots
=  ::demo::Page::slot::creator ::demo::Page::slot::page_order ::demo::Page::slot::mime_type ::demo::Page::slot::page_id

>> ::xo::slotobjects ::demo::Page
=  ::demo::Page::slot::creator ::demo::Page::slot::page_order ::demo::Page::slot::mime_type ::demo::Page::slot::page_id ::xo::db::CrItem::slot::package_id ::xo::db::CrItem::slot::nls_language ::xo::db::CrItem::slot::description ::xo::db::CrItem::slot::name ::xo::db::CrItem::slot::text ::xo::db::CrItem::slot::publish_status ::xo::db::CrItem::slot::parent_id ::xo::db::CrItem::slot::title ::xo::db::CrItem::slot::revision_id ::xo::db::CrItem::slot::item_id ::xo::db::Object::slot::object_title ::xo::db::Object::slot::object_id

.. create page
>> set i [Page new  \
     -name "page0"  \
     -title "Joke of the Month" \
     -creator "GN" \
     -text "Three cannibals meet in a NYC subway station..."  ]
=  ::xotcl::__#j

>> $i save_new
=  7855

.. show contents of page object ::xotcl::__#j (including creator and page_order,
.. when ltree is available)

::demo::Page create ::xotcl::__#j -noinit \
    -set page_order {} \
    -set creator GN \
    -set page_id {} \
    -set creation_date {2007-09-03 23:28:29.149591+02} \
    -set object_id 7855 \
    -set creation_user 0 \
    -set description {} \
    -set text {Three cannibals meet in a NYC subway station...} \
    -set nls_language en_US \
    -set mime_type text/html \
    -set name page0 \
    -set publish_status ready \
    -set title {Joke of the Month} \
    -set revision_id 7854 \
    -set item_id 7855 \
    -set last_modified {2007-09-03 23:28:29.149591+02} \
    -set parent_id -100 

>> set item_id [::xotcl::__#j item_id]
=  7855

>> ::xotcl::__#j destroy

>> ::demo::Page get_instance_from_db -item_id 7855
=  ::7855

::demo::Page create ::7855 -noinit \
    -set page_order {} \
    -set object_type ::demo::Page \
    -set page_id 7854 \
    -set creation_date {2007-09-03 23:28:29.149591+02} \
    -set object_id 7854 \
    -set creation_user 0 \
    -set description {} \
    -set text {Three cannibals meet in a NYC subway station...} \
    -set nls_language en_US \
    -set package_id 492 \
    -set name page0 \
    -set mime_type text/html \
    -set title {Joke of the Month} \
    -set publish_status ready \
    -set revision_id 7854 \
    -set item_id 7855 \
    -set last_modified {2007-09-03 23:28:29.149591+02} \
    -set parent_id -100 \
    -set creator_string GN

Code Formatting

Created by Rocael Hernández Rizzardini, last modified by Gustaf Neumann 14 Feb 2018, at 09:07 AM

  • Use 4 space indentation 
  • Code lines must not exceed 80 characters in length. Never use a single line that has more than 80 chars.
  • Source files should be coded in UTF-8 using Unix-style newlines

These general rules are applicable to Tcl & SQL.

Also, the 80 character limit is important because the OpenACS API browser (at /api-doc/) presents documentation defined in ad_proc's doc_string declaration in html format; whereas ad_proc's body of code is presented wrapped in PRE tags. Longer code lines result in API documentation pages (and their paragraphs) stretching outside of typical browser window width.

If you are using Emacs editor, you usually are on the safe side with regards to Tcl, as the tcl-mode indents just as we want it. ADP pages are formatted correctly when editor is in html-mode.

Formatting SQL Statements

  • A proper format for select statements is
    select ....
    from ....
    where clause
        and clause
        and clause
  • A proper format for insert statements (and note the indentation and overflow of attributes)
    insert into table_name
      (c1, c2, c3 ...
       cx, cy, cz)
    values
      (v1, v2, v3 ...
       vx, vy, vz)
  • A proper format for update statements:
    update table
    set c1=v1,
         c2=v2,
         ...
    where ...

Editor modes

There is an OpenACS mode for emacs OpenACS mode for Emacs which has features to help meet formatting standards.

One can add the following stanza to the end of a .tcl file, when using Emacs, to avoid, that spaces are changed again into tabs.

#
# Local variables:
#    mode: tcl
#    tcl-indent-level: 4
#    indent-tabs-mode: nil
# End:

 

Security Considerations

Allowing user input to include images, see patch in this discussion thread: https://openacs.org/forums/message-view?message_id=182057

Boomerang Plugin

Created by Gustaf Neumann, last modified by Gustaf Neumann 11 Jan 2018, at 01:41 PM

Package Specification Summary for Package: boomerang

Summary: Boomerang is a JavaScript library to measure the performance of your website from your end user’s point of view. It has the ability to send performance data measured at the client back to the server via a beacon URL further analysis. The boomerang library implements Real User Measurement (RUM) to measure the performance experience of real users by collecting quality indicators from the clients. The boomerang library is released under the BSD license. Details: https://soasta.github.io/boomerang/doc/ This package integrates boomerang with OpenACS, in particular with OpenACS subsites.
Description:
Maturity: Immature
This package depends on: acs-templating acs-tcl
Packages that depend on boomerang: None
Package parameters:
Version
Version of the boomerang library (default 1.737.0, type string, scope instance)

Bug Tracker Summary for Package: boomerang

There is no package with the name "boomerang" known to bug-tracker.


Code Metrics Summary for Package: boomerang

# Tcl Procs 6
# Tcl Lines 650
# Tcl Blank Lines 74
# Tcl Comment Lines 172
# Automated Tests 0
# Stored Procedures PG: 0 ORA: 0
# SQL Lines PG: 0 (blank 1 comments 0) ORA: 0 (blank 1 comments 0)
# ADP pages 1
# ADP lines 41
# Include pages (boomerang/lib/) 0
# Documentation pages 0
# Documentation lines 0
Browse Source API-browser
Github Repository: https://github.com/openacs/boomerang/tree/oacs-5-10

Integration of the Boomerang library as an OpenACS Plugin

Boomerang is a JavaScript library to measure the performance of your website from your end user’s point of view. It has the ability to send performance data measured at the client back to the server via a beacon URL further analysis.  The boomerang library implements Real User Measurement (RUM) to measure the performance experience of real users by collecting quality indicators from the clients.

The boomerang library is released under the BSD license.

Details:
    https://soasta.github.io/boomerang/doc/

This package integrates boomerang with OpenACS, in particular with OpenACS subsites.


Features

  • Obtain client site timings to measures the performance of your  website from your end user's point of view.
  • Support sampling (e.g. just obtain metrics from every nth request)
  • Output performance data in a format suitable for feeding into  Elasticsearch/Logstash (see below for example config files)
  • Configure the appearance of the boomerang per subsite with  the following parameters:
     
    BoomerangEnabled 0|1
    BoomerangSample 1
    BoomerangBeaconUrl  /boomerang_handler
     
    The parameter BoomerangSample can be used for busy sites to sample not every request (when the value is 1), but e.g. every 5th request (setting BoomerangSample to 5).
  • Support for host-node-mapped subsites
  • Site-wide admin support for compressing .js file
  • Performance: include boomerang in the template costs about 0.3ms, processing of the beacon call takes about 1ms (filter times).


Installation

  1. Install this package via the OpenACS Package Manager
     
  2.  Add this package to the templating system
     
    • OpenACS 5.10.0d2 or newer:
      The boomerang plugin uses the "subsite::page_plugin" callback, so no changes on templates are necessary. Make sure to update as well the acs-bootstrap-installer to 5.10.0d2 or newer to obtain the updated blank-master.
       
    • OpenACS 5.9.1:
      Add to the top of your blank-master.tcl the following snippet:
            if {[info commands ::boomerang::initialize_widget] ne ""} {
                ::boomerang::initialize_widget
            }
  3.  Configure in the parameters of the subsite (e.g. the main subsite) the section "Boomerang Plugin"

 

Usage

For the explanation of the parameters, see:
     https://soasta.github.io/boomerang/doc/howtos/howto-0.html
     https://soasta.github.io/boomerang/doc/api/RT.html
     https://soasta.github.io/boomerang/doc/api/navtiming.html    
 

Prerequirements

The implementation uses nx from the next-scripting framework.

    https://next-scripting.org/xowiki/

which is automatically installed for XOTcl2 via naviserver-openacs. It works best with OpenACS 5.10.0d2 or newer, but works as well with 5.9.1 (see INSTALLATION section above) or earlier versions with little adaptions

 

OPTIONAL: Define a custom Boomerang Plugin

  1. Clone boomerang repository
  2. Install npm, grunt if necessary
  3. Follow step 2 in https://github.com/SOASTA/boomerang     which means
          ... configure plugins
          ... grunt clean build
  4. The result is in the build directory. The generated files have the a build-time stamp in seconds included. You might which to rename these with a custom name.
  5. Copy the the *.min.js and *.min.js.gz files to the boomerang/www/resouces directory, which might be
    cp  build/boomerang-1.0.*.min.js build/boomerang-1.0.*.min.js.gz ..
    and adapt the version number in the boomerang parameters (on /acs-subsite)
     

     

OPTIONAL: Feed Boomerang Data into an elasticsearch cluster

When boomerang is enabled, the results of the beacon are placed into
the OpenACS log directory with a name boomerang-*.log (containing the date).

Below are sample-snippets from OpenACS.org the log-files into elasticsearch,
such that it can be analyzed later with kibana or grafana.

Example filebeat entry for the data feed:

      paths:
        - /var/www/openacs.org/log/boomerang-*.log
      input_type: log
      fields:
          log_type: boomerang-log


Example logststash entry (input filter for transforming the data from filebeat and to feed it into easticsearch)

  if [fields][log_type] == "boomerang-log" {
    json {
       source => "message"
       remove_field => [ "restiming" ]
    }
    grok {
       match => [ "source", "/var/www/%{GREEDYDATA:server}/log/boomerang-" ]
    }    
    geoip { source => "clientip" }
  }

 

Example Analysis Screenshots from OpenACS

The following chart shows performance indicators of OpenACS.org over the last two days. The topmost chart is produced with grafana and shows elapsed time (left axis) and number of requests (right axis). "Average runtime" is the time measured on the server (how long does it take the server to fulfill the requests), whereas "Average t_done" is the time it took the browser to render the page (stating at the click). "t_done" is a default measurement provided by boomerang. Note, that the values from boomerang require that JavaScript is active at the client side (i.e. there are typically no spiders included in this value, as well only views).

OpenACS performance 2 days

We can see from these values that the average runtime is 36ms, while the full render time is on average 2.2s (about 60x larger). One reason is that static content is served quite fast.  The second chart is as well produced with grafana and analyses the phases of requests based on W3C Navigation Timing. The nt_response_time shows the client point of view how long it took the server to provide an response to the request.

OpenACS performance 2 days

We can see that nt_response_time is about 100ms (it takes longer to server the dynamic html files). Also from this point of view the response time of the server for the main request only contributed a fraction of the total time. The longest time is the processing time in the client, which depends on the content, CSS, JavaScript, etc. Note that these are overall values, averaging over all requests. One can certainly drill down on certain pages for more details.

Another interesting aspect is the geographic location: has the client a good internet connection in respect to the server? The first map was produced with kibana and shows from which geographic locations pages of OpenACS.org were requested over the last week. Locations with more requests are shown emphasized.

OpenACS requests 7 days

We see that the highest number of requests are coming from the US (Seattle and Washington areas), and in Europe is Austria (Vienna) and France (Paris) issued many requests. If we analyze for boomerang requests with high values of "t_done", we see that these requests are coming from regions far away from Vienna, where the server is located (e.g. from Asia, South America, Australia)

OpenACS requests 7 days slow requests

 

 

OpenACS Reference Platform

Created by OpenACS community, last modified by Robert Taylor 29 Dec 2017, at 03:23 PM

These are the defaults we create and use during the standard installation process, in helper scripts and other places. None of these locations are set in stone - they're simply the values that we've chosen.

Default directories for a standard install

Fully qualified domain name of your server yourserver.test
name of administrative access account remadmin
OpenACS service service0
OpenACS service account service0
OpenACS database name service0
SERVERROOT - base of the OpenACS service file tree /var/lib/aolserver/service0
Location of source code tarballs for new software /var/tmp
The OpenACS tarball contains some files which are useful while setting up other software. Those files are located at: /var/lib/aolserver/service0/packages/acs-core-docs/www/files
Database backup directory /var/lib/aolserver/service0/database-backup
Service config files /var/lib/aolserver/service0/etc
Service log files /var/lib/aolserver/service0/log
Base compile directory /usr/local/src
PostgreSQL directory /usr/local/pgsql
AOLserver directory /usr/local/aolserver

Some instructions provide cut and paste conveniences

In order for some copy and paste instructions to work in your bash shell, you must set the environment variable $OPENACS_SERVICE_NAME. Add this line to your .bashrc or .profile_bash file to set the environment variable for a specific user:

export OPENACS_SERVICE_NAME=service0

To set it globally so that it works for any new users or special service users you may create, add the above line to the file /etc/profile

$OPENACS_SERVICE_NAME is set to the value of service0 on a default install. Change service0 to a word that better represents your project. The other values we recommend you leave unchanged unless you have a reason to change them.

A service name ($OPENACS_SERVICE_NAME) should be a single word, letters and numbers only. If the name of your site is one word, that would be a good choice. For example "$OPENACS_SERVICE_NAME" might be the service name for the OPENACS_SERVICE_NAME.net website.

Some discussion that lead to these default values: https://openacs.org/forums/message-view?message_id=82934

Commit Messages

Created by Gustaf Neumann, last modified by Gustaf Neumann 29 Dec 2017, at 10:11 AM

  • Write your commit message in the imperative present tense: Use "Fix bug" and not "Fixed bug" or "Fixes bug." This convention matches up with commit messages generated by commands like git merge and git revert. It should start with a verb like "Fix", "Add" or "Change".
  • Commit message should contain a title and an optional body.
  • The title of the commit message should be a capitalized, short (50 chars or less) summary, not ending with a period.
  • The title can be followed by the body, an explanatory text, if necessary. Title and body are separated by an empty line. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together.
  • The body should be wrapped to 72 characters.  The body can contain multiple paragraphs, containing plain text or bullet points. The bullet points should be typed as a hyphen or asterisk with blank lines in between. Use a hanging indent for longer bullet points
  • Make white-space changes separately

See also:

Cookie Consent Widget

Created by Gustaf Neumann, last modified by Gustaf Neumann 22 Dec 2017, at 06:55 PM

Package Specification Summary for Package: cookie-consent

Summary: Cookie Consent Widget based on the free Cookie Consent Library
Description:
Maturity: Immature
This package depends on: acs-templating acs-tcl
Packages that depend on cookie-consent: None
Package parameters: None

Bug Tracker Summary for Package: cookie-consent

There is no package with the name "cookie-consent" known to bug-tracker.


Code Metrics Summary for Package: cookie-consent

# Tcl Procs 9
# Tcl Lines 517
# Tcl Blank Lines 64
# Tcl Comment Lines 93
# Automated Tests 1
# Stored Procedures PG: 0 ORA: 0
# SQL Lines PG: 0 (blank 1 comments 0) ORA: 0 (blank 1 comments 0)
# ADP pages 1
# ADP lines 7
# Include pages (cookie-consent/lib/) 0
# Documentation pages 0
# Documentation lines 0
Browse Source API-browser
Github Repository: https://github.com/openacs/cookie-consent/tree/oacs-5-10

Integration of the Cookie Consent Library into OpenACS

The Cookie Consent Library is and Cookie Consent to be free and open sourced library for for alerting users about the use of cookies on a website.  It is designed to help you comply with the hideous EU Cookie Law and not make you want to kill yourself in the process. So we made it fast, free, and relatively painless.

Details:
    https://cookieconsent.insites.com/
    https://github.com/insites/cookieconsent/

This package integrates the Consent Plugin with OpenACS, in particular with OpenACS subsites.

So far, this package supports on the "inform" type of cookie consent policies. When the "opt-out" or "opt-in" variants of the policies should really include all types of cookies (even session-cookies) the user would not be able to login to the site. However, most countries stick for now to the "inform" policy, and the detailed regulation are still in flux.

Features:

  •  Configure the appearance of the cookie consent widget via the following parameter (on acs-subsite):
     
    CookieConsentEnabled 0|1
    CookieConsentPosition bottom|top|pushdown|left|right
    CookieConsentLayout block|classic|edgeless|wire
    CookieConsentPalette oacs|honeybee|mono|neon|corporate
    CookieConsentLearnMoreLink https://cookiesandyou.com/
    CookieConsentDefaultPalette  

     

  • Usage from CDN (out-of-the box) or from a local copy (download your local copy via   "Site-Wide Admin" link in /acs-admin/)
  • Support for host-node-mapped subsites
  • Internationalized with OpenACS message keys


Installation

  1.  Install this package via the OpenACS Package Manager
  2.  Add this package to the templating system
     
    •  OpenACS 5.10.0d2 or newer:
       The cookie consent widgets uses the "subsite::page_plugin" callback, so no changes on templates are necessary. Make sure, you update also acs-bootstrap-installer to 5.10.0d2 or newer to obtain the updated blank-master
       
    • OpenACS 5.9.1:
      Add to the top of your blank-master.tcl the following snippet:
       ================================================================
      if {[info commands ::cookieconsent::initialize_widget] ne ""} {
            ::cookieconsent::initialize_widget
      }
      ================================================================
  3. Configure the CookieConsent* parameters of the subsite (e.g. of the main subsite) in the section "Cookie Consent"

Prerequirements:

The implementation uses nx from the next-scripting framework.

    https://next-scripting.org/xowiki/

which is automatically installed for XOTcl2 via naviserver-openacs

It works best with OpenACS 5.10.0d2 or newer, but works as well with 5.9.1 (see INSTALLATION section above) or earlier versions supporting Content Security Policy (CSP), and probably with  earlier versions as well, when CSP code is commented out.

 

 

 

Richtext CKEditor 5

Created by Gustaf Neumann, last modified by Gustaf Neumann 21 Dec 2017, at 09:28 AM

Package Specification Summary for Package: richtext-ckeditor5

Summary: Richtext editor plugin for integrating CKeditor 5 with the acs-templating richtext widget
Description:
Maturity: New Submission or Maturity Unknown
This package depends on: acs-templating acs-tcl xotcl-core attachments
Packages that depend on richtext-ckeditor5: None
Package parameters:
SCAYT
Fully featured "Spell Check As You Type" based on WebSpellChecker.net. Please note that the spellchecked words are transferred to that site, so you might be cautious to activate this feature for confidential content. (default false, type string, scope instance)

Bug Tracker Summary for Package: richtext-ckeditor5

There is no package with the name "richtext-ckeditor5" known to bug-tracker.


Code Metrics Summary for Package: richtext-ckeditor5

# Tcl Procs 10
# Tcl Lines 622
# Tcl Blank Lines 84
# Tcl Comment Lines 131
# Automated Tests 0
# Stored Procedures PG: 0 ORA: 0
# SQL Lines PG: 0 (blank 1 comments 0) ORA: 0 (blank 1 comments 0)
# ADP pages 1
# ADP lines 20
# Include pages (richtext-ckeditor5/lib/) 1
# Documentation pages 0
# Documentation lines 0
Browse Source API-browser
Github Repository: https://github.com/openacs/richtext-ckeditor5/tree/oacs-5-10

In general, the CKEditor 5 can be used via CDN (zero configuration, default) or via local files. One can use /acs-admin/ (section Site-wide Service Administration to download a version to your local site to reduce latency or to use local modifications.

So far, CKeditor 5 is not released yet, this integration is just minimal, no xowiki formfield support is included yet.

.LRN Accessibility

Created by Olga C. Santos, last modified by Gustaf Neumann 25 Oct 2017, at 08:34 AM

From quite a long time .LRN community has been moving towards producing both accessible interfaces and services for all. Accessibility analysis on previous releases have been done such as Tristan Kalnins-Cole's under Dorian Peter's (dotLRN Director of Visual Design) supervision. This lead to the unofficial conclusion that version 2.1.3 was level A compliant.

Selva theme was designed to make easier the customization of the look and feel of .LRN, improving navigation and usability. Moreover, unlike other .LRN templates, it is strongly based on CSS. Therefore, it can be easily seen that Selva theme was a step forward in considering accessibility issues.

During the development of version 2.2.0 we have been working to assure that .LRN 2.2.0 with Selva theme is compliant at least with W3C WAI WCAG 1.0 level A. In this sense, three new categories of bugs have been created in the Bug Tracker and are being used to report problems regarding accessibility. So far, within the framework of several R&D projects in which aDeNu Research Group at UNED is involved, we have compiled several accessibility analysis performed by some of our partners (Soluziona) and research groups within UNED to translate the problems found at different development stages to .LRN/OpenACS bugs and discuss them in the .LRN IRC Tuesday meetings. "This work has led to the release of .LRN 2.2.0 as W3C WAI WCAG 1.0 level A compliant, except for LORS package (there is a strong incompatibility between the SCORM RTE and WCAG 1.0, which is to be solved with WCAG 2.0). Moreover, there may be some minor level A bugs reported found here, which are to be solved."

The planning for next version is to achieve WC3 WAI WCAG level AA and take into account, when available, specific guidelines from national regulations such as the American Section 508, UK SENDA, Australian DDA, German BITV or Italian Stanca. Our plans are to consider WCAG 2.0 as soon as they are officially released as well as other WAI documents (e.g. ATAG and UAAG).

In order to improve the accessibility quality of dotLRN, we ask you to use W3C Web Content Accessibility bug types to report any problems encountered so they are taking into account when developing.

Update for dotLRN 2.3

See Zen project and external evaluations on Educational packages [1], [2].

Information on the progress is also done in periodic dotLRN/OpenACS conferences:

  • Fall 2006
  • Spring 2007
    • Improving Accessibility, Usability, and Code Quality of .LRN and OpenACS: The .LRN Zen Project [3]
    • Workshop on Experiences on Accessible eLearning Platforms

 

Last modified: 2017-10-25 08:34:57.234495+02

Ajax Helper

Created by Hamilton Chua, last modified by Gustaf Neumann 25 Oct 2017, at 08:32 AM

Package Specification Summary for Package: ajaxhelper

Summary: Ajax Helper for various javascript libraries.
Description: Provides helper procs to generate javascript used for Ajax and generating cinematic effects. Includes Scriptaculous 1.7.1 beta3 with Prototype 1.5.1, ExtJS 1.1.1 and the Yahoo UI Libraries (2.3.0). As of 0.87d, there is now an option to load YUI js source files direct from yahoo (http://developer.yahoo.com/yui/articles/hosting/). Lee Denison's template::head is now used to load javascript sources and css. The YUI loader is used to intelligently load YUI sources and css. As of 0.7d, all javascript libraries have been moved to ajaxhelper/www/resources to take advantage of caching. As of 0.8d, the wrappers will now be able to check a global variable to see if the required sources are loaded, this allows helper procs to automatically load the javascript sources you need.
Documentation: Package Documentation
Maturity: Immature
This package depends on: acs-kernel acs-tcl
Packages that depend on ajaxhelper: ajax-filestorage-ui ajax-photoalbum-ui connections contacts eduwiki learning-content messages planner scorm-player
Package parameters:
LoadJsfromYahoo
Set this parameter to 1 if you wish to load YUI javascript sources from yahoo's servers. (default 0, type number, scope instance)
UseMinifiedJs
Set this parameter to 1 if you want ajaxhelper to load minified versions of the javascript sources whenever possible. (default 0, type number, scope instance)


Bug Tracker Summary for Package: ajaxhelper

There is no package with the name "ajaxhelper" known to bug-tracker.



Code Metrics Summary for Package: ajaxhelper

# Tcl Procs 67
# Tcl Lines 2784
# Tcl Blank Lines 514
# Tcl Comment Lines 67
# Automated Tests 0
# Stored Procedures PG: 0 ORA: 0
# SQL Lines PG: 0 (blank 1 comments 0) ORA: 0 (blank 1 comments 0)
# ADP pages 15
# ADP lines 147
# Include pages (ajaxhelper/lib/) 1
# Documentation pages 9 (Package Documentation)
# Documentation lines 1400
Browse Source Not installed
Github Repository: https://github.com/openacs/ajaxhelper/tree/oacs-5-10

 

Ajax Helper is a package created to assist OpenACS developers incorporate Ajax into their web applications. It is composed of helper procs that wrap javascript functions that perform DHTML effects and Ajax. 

Ajax Helper incorporates javascript from Thomas Fuch's Scriptaculous Javascript Library (http://script.aculo.us) and Yahoo's User Interface Library or YUI ( http://developer.yahoo.com/yui/ ).

Tutorials on how to use Ajax Helper :

Introduction to Ajax Helper with Simple Effects
http://web.archive.org/web/20111221205659/http://www.solutiongrove.com/blogger//one-entry?entry%5fid=266153

Using Ajax
http://web.archive.org/web/20060715115103/http://www.solutiongrove.com:80/blogger/one-entry?entry%5fid=268010

Simple Drag and Drop
http://web.archive.org/web/20060715115051/http://www.solutiongrove.com:80/blogger/one-entry?entry%5fid=266155

Current Release on CVS HEAD : AjaxHelper 0.87d
includes Scriptaculous v.1.7.3 Beta, YUI v. 2.3.0 and ExtJs 1.1.1
 

 

Assessment Admin UI

Created by Caroline Meeks, last modified by Gustaf Neumann 20 Oct 2017, at 05:25 AM

TODO LIST

  • Update this page with the latest work
  • Carl will fill in here... 

 The current UI is very confusing and cluttered.

Our vision of a final UI is that a assessment creator would pick a type of assessment he wants and the site will set all defaults appropriately for it. However, the first attempt to do this was a failure so we are working on an incremental approach that we think will provide value with minimal effort. Our intent is that later we move to an even friendlier UI.

 Incremental Improvement Vision:  The current user experience is: every time you create anything you are confronted by many many choices, most of which you can ignore. Similarly all the admin pages have many repeated buttons and its not clear when you want to do what.  Thus our goal is:

  • Creation pages are very very simple and useful defaults are set for everything.
  • Objects then have one button to an Edit page that has all the complex things you can do with the object.

Related Pages:

Screenshots

These are screenshots of the work in progress.

 

Simplified quick assessment creation form. 

 

One Assessment Admin Page 

 

One Section Admin Page

 

 

 Add a question page.

First the original question form:

Now the new form. The question creation process used to require filling out 3 forms. We compressed it to one form by removing unused settings, and making intelligent default decisions. Some more work needs to be done. Assessment has a huge amount of complex features and it is not clear how they are used together to create a certain type of assessment. It is clear that all of the settings rarely need to be used together.

 

Next Page
previous March 2026
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4

Popular tags

17 , 5.10 , 5.10.0 , 5.10.1 , 5.9.0 , 5.9.1 , ad_form , ADP , ajax , aolserver , asynchronous , Azure , bgdelivery , bootstrap , bugtracker , CentOS , COMET , compatibility , conference , CSP , CSRF , cvs , debian , docker , docker-compose , emacs , engineering-standards , exec , fedora , FreeBSD
No registered users in community xowiki
in last 30 minutes
Contributors

OpenACS.org