% Hacking Open Atrium: adding Features within the Contexts of your Spaces % Steve Mokris % 2011.12.03 # Background Game Research and Immersive Design (GRID) Lab [http://gridlab.ohio.edu/](http://gridlab.ohio.edu/) > - department at Ohio University (Athens, Ohio) > - teach undergraduates about video game development > - research projects — simulations, 3D graphics, computer vision # Background (Continued) Drupal @ the GRID Lab > - 2008: Drupal 6.x public site + intranet > - intranet — task manager, wiki, inventory, ... - built with CCK + Views + Taxonomy - a Term for every Project - Taxonomy Access Control (TAC) > - **difficulty scaling** — all-or-nothing administration # Background (Continued) Drupal @ the GRID Lab > - 2009 fall: replaced homebrew intranet with Open Atrium (1.0-beta3) > - intranet — casetracker, book.module wiki, ... > - an Organic Group for every Project > - **scales better** — each Group has one or more Admins, not necessarily site-wide > - importing content from old Drupal 6.x site to new Drupal 6.x site == problematic > - (Drupal is 10 years old and it still doesn't have a robust way to transfer content between sites? Someday I'll fix that...) > - customizations: inventory, assignments, jobs board, production workflow, glossary, ... # Background (Continued) Kosada, Inc. [http://kosada.com/](http://kosada.com/) > - software development company — Mac, iOS, Drupal > - both internal projects and commissioned projects # Background (Continued) TWiki @ Kosada > - using TWiki since 1999 > - very powerful, flexible, and well-designed Wiki > - not database-backed => difficult to perform complex queries > - relatively small development community # Background (Continued) Drupal @ Kosada > - 2010 spring: replaced TWiki intranet with Open Atrium (1.0-beta5) > - customizations: time tracking, integration with Xero (web accounting system) # Prerequisites - features.module - context.module - spaces.module # features.module > - Drupal contrib [features.module](http://drupal.org/project/features): database configuration data => code > - Drupal Core stuff (content types, CCK fields, input formats, menus, taxonomy vocabularies, permissions) > - database variables (using [strongarm.module](http://drupal.org/project/strongarm)) > - roles ([roles_export.module](http://drupal.org/project/roles_export) is helpful) > - [views.module](http://drupal.org/project/views) views (CTools Exportables) > - content (using [uuid_features](http://drupal.org/project/uuid_features)) # Capital-F Features > - A (capital-f) Feature is a bunch of configuration data exported as code > - since it's code you get to use **Revision Control**. > This is good. > - each Feature module's .info file => stakes claims # Feature Example [http://drupal.org/project/debut](http://drupal.org/project/debut) (a set of Features for Drupal 7.x) > - Debut Blog [look at debut_blog.info] [look at debut_blog.module] # Feature Example 2 http://kineme.net/ > - public web forum (about 3,000 users and 22,000 posts) > - several roles (anonymous, new user, established user, advanced user, forum admin, site admin) => complex permissions > - (don't let anonymous post unmoderated comments) > - codify permissions => kineme_policy.module (a Feature!) # Other Features [http://drupal.org/project/features](http://drupal.org/project/features) ![Features: Other contributed modules](drupal-project-features-other.png) # Features: Kit [http://drupal.org/project/kit](http://drupal.org/project/kit) - use a unique name - http://drupal.org/project/[myfeature] - prefix everything with that unique name # Site-Specific Features Features can get fairly personal, might not make sense to post on drupal.org > - => run your own private Feature Server [http://drupal.org/project/fserver](http://drupal.org/project/fserver) # Capital-C Contexts > - A (capital-c) Context is a subset of pages on a site (and optionally things do do when one of those pages is active) # context.module > - provides UI for defining which pages are part of each Context. > similar to Drupal Core's "Page specific visibility settings" for Blocks, but much more flexible. ![Drupal Core's "Page specific visibility settings" for Blocks](block-page-visibility.png) # Context example hypothetical site with static content (node.module), news (blog.module, comment.module), and a user community (forum.module, poll.module). Block requirements: > - Static Content: show only recent news and popular forum posts > - News: show only news categories and chronological archives > - Community: show only list of forums and active poll # Context example (Page 1 of 3) therefore: - make a "Static Content" Context: - Conditions: - Node type: Page - _or_ Path: contact - Reactions: - Blocks: Recent News, Popular Forum Posts # Context example (Page 2 of 3) therefore: - make a "Static Content" Context - make a "News" Context: - Conditions: - Node type: Story - _or_ Taxonomy: News Category - _or_ Views: Blog Listing - Reactions: - Blocks: News Categories, Archives # Context example (Page 3 of 3) therefore: - make a "Static Content" Context - make a "News" Context - make a "Community" Context: - Conditions: - Node Type: Forum - Reactions: - Blocks: Forum List, Current Poll # spaces.module > - Drupal contrib [spaces.module](http://drupal.org/project/spaces): override site-wide configuration for only a portion of a site (a capital-s Space) > - a Space for every { User | Taxonomy Term | Organic Group } > - contrib: a Space for every [Node](http://drupal.org/project/spaces_node) # How Open Atrium Does It > - every Open Atrium "Group" is an Organic Group > - via spaces_og.module, every Organic Group is also a Space => so you can enable Features per Space > - via [purl.module](http://drupal.org/project/purl), every Organic Group has a URL path prefix => specifies which Group is active (i.e., needed pages which aren't attached to a specific Group) # Built-in Open Atrium Features (each can be toggled per Group) - Blog (based on Drupal Core's blog.module) - Notebook (based on Drupal Core's book.module) - Case Tracker (based on Contrib [casetracker.module](http://drupal.org/project/casetracker)) - Calendar (based on Drupal Core's node.module) - Shoutbox (based on Drupal Core's node.module) - Dashboard (based on spaces_dashboard.module) - Members (just Views) # Third-party Open Atrium Features [http://community.openatrium.com/node/441](http://community.openatrium.com/node/441) # Making a New OA Feature (1 of 3) > - use the Drupal UI to build it normally - create Node Type, Menus, Views, Blocks, ... - under the "Organic Groups" settings, be sure to make the Node type a "Standard group post - for Menu items, use the top-level "Features" menu > - export to a Feature module > - define Spaces scope for the Feature — in your_feature.info - spaces[types][] = "og" > - enable the Feature # Making a New OA Feature (2 of 3) > - update your Views (if any) - Access: "Spaces feature" - Filter: "Spaces: Content in current space" > - create an icon - 40x40 pixel PNG with alpha > - add CSS rules for your icons #features-menu li a.icon-myfeature span.icon { background:url(myfeature.png) no-repeat; } .feature .feature-myfeature { background:transparent url(myfeature.png) no-repeat; } .feature-myfeature { background:url(myfeature.png) no-repeat !important; } # Making a New OA Feature (3 of 3) > - add the CSS /** * Implementation of hook_init(). */ function myfeature_init() { drupal_add_css(drupal_get_path('module', 'myfeature') .'/myfeature.css'); } # The Jobs Board ![GRID Lab Callboard](gridlab-callboard.png) # The Jobs Board [insert demo here] # Some Other Open Atrium Features - [Answers](http://drupal.org/project/atrium_answers) - Assignments - [Glossary](http://drupal.org/project/atrium_glossary) - Inventory - Production Workflow Tracker # End - third-party Features [http://community.openatrium.com/node/441](http://community.openatrium.com/node/441) - docs on building Open Atrium Features [https://community.openatrium.com/node/449](https://community.openatrium.com/node/449) - talk to me mokris@ohio.edu