aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorFilipp Lepalaan <f@230.to>2013-11-08 09:31:01 +0200
committerFilipp Lepalaan <f@230.to>2013-11-08 09:31:01 +0200
commitf077badf3163fc36c111dc45fe8d7d6f57d8712a (patch)
treef2b83bdc836f8a8035badb0d401ee0ea86eafa55 /apps
parentb9fc1060406a433473faa70c236ba3e177640d26 (diff)
downloadmotor.old-f077badf3163fc36c111dc45fe8d7d6f57d8712a.tar.gz
motor.old-f077badf3163fc36c111dc45fe8d7d6f57d8712a.tar.bz2
motor.old-f077badf3163fc36c111dc45fe8d7d6f57d8712a.zip
Merged motor and checkin
Diffstat (limited to 'apps')
-rw-r--r--apps/__init__.py0
-rw-r--r--apps/checkin/README.rst103
-rw-r--r--apps/checkin/__init__.py0
-rw-r--r--apps/checkin/checkin.mindnode/QuickLook/Preview.jpgbin0 -> 57589 bytes
-rw-r--r--apps/checkin/checkin.mindnode/contents.xml1507
-rw-r--r--apps/checkin/checkin.mindnode/style.mindnodestyle/contents.xmlbin0 -> 1483 bytes
-rw-r--r--apps/checkin/checkin.mindnode/style.mindnodestyle/metadata.plistbin0 -> 152 bytes
-rw-r--r--apps/checkin/checkin.mindnode/viewState.plistbin0 -> 185 bytes
-rw-r--r--apps/checkin/models.py94
-rw-r--r--apps/checkin/tests.py16
-rw-r--r--apps/checkin/views.py1
-rw-r--r--apps/core/__init__.py0
-rw-r--r--apps/core/admin.py3
-rw-r--r--apps/core/forms.py12
-rw-r--r--apps/core/models.py59
-rw-r--r--apps/core/templates/login.html2
-rw-r--r--apps/core/tests.py3
-rw-r--r--apps/core/views.py17
-rw-r--r--apps/docs/__init__.py0
-rw-r--r--apps/docs/admin.py5
-rw-r--r--apps/docs/models.py27
-rw-r--r--apps/docs/templates/default.html78
-rw-r--r--apps/docs/templates/docs_index.html8
-rw-r--r--apps/docs/templates/docs_view.html8
-rw-r--r--apps/docs/templates/terms.html256
-rw-r--r--apps/docs/templatetags/__init__.py0
-rw-r--r--apps/docs/templatetags/motor_tags.py13
-rw-r--r--apps/docs/tests.py16
-rw-r--r--apps/docs/views.py19
-rw-r--r--apps/troubleshooting/__init__.py0
-rw-r--r--apps/troubleshooting/models.py19
-rw-r--r--apps/troubleshooting/tests.py16
-rw-r--r--apps/troubleshooting/views.py1
33 files changed, 2283 insertions, 0 deletions
diff --git a/apps/__init__.py b/apps/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/__init__.py
diff --git a/apps/checkin/README.rst b/apps/checkin/README.rst
new file mode 100644
index 0000000..871037b
--- /dev/null
+++ b/apps/checkin/README.rst
@@ -0,0 +1,103 @@
+Introduction
+============
+Servo Checkin is a tool for checking in Apple hardware for service. It's designed for consumers, business customers and service providers. Should work on both desktop and mobile devices. The service will be a free public service for consumers to manage their Apple hardware and a paid service for Service Providers (SP) who can:
+- Link to the service from their homepage
+- Use the service at their stores as a self-service system
+
+Business customers should be able to check in their service cases with a certain SP as well as receive updates and give feedback on a case.
+
+Each "instance" is always tied to a specific SP. The customer always starts withs https://checkin.servoapp.com/$sp
+
+
+Features
+========
+Customers should be able to:
+- Create an account and manage their Apple hardware
+- Check in a device for service without creating an account
+- Check the status of their current service cases (if they've created an account)
+
+
+Managing hardware
+=================
+- Customers should be able to check the warranty of their device.
+- Upload purchase receipts and other relevant documents. Mark a device as stolen (?).
+- Check part prices (with proper service provider backend)
+- Check the specs of the machine (what type of RAM, supported OS, etc)
+- See current repair extension programs for the device
+
+
+Creating a Service Case
+=======================
+- Choose language
+- Enter serial number
+- Enter problem description
+- Enter username and password
+- Enter whether data backup is necessary
+- Enter maximum price for repair (if OOW)
+- Troubleshooting
+
+
+During service
+==============
+- Customers should be able to check the status of the repair
+- See the latest reported notes by the technician
+- See the totall cost of the repair
+- Authorize or decline a cost estimate
+
+
+After service
+=============
+- Customers should be able to give feedback on the case
+- Rate the case (1-5 on speed, professionalism... check CSAT)
+- Overall time to repair completion
+- Professionalism of the service location employees
+- Quality of the repair and condition of the repaired product
+- Timeliness of updates provided, especially if the repair is delayed
+- Follow-up? (somehow checking that the problem is really gone?)
+
+
+Troubleshooting
+===============
+- Help the customer describe the problem
+- Help the service provider get the information they need
+- Admin-configurable (question: choices)
+- Creates a "story"
+
+
+Backends
+========
+Servo Checkin should be a separate product from Servo. This would allow:
+- providing a public service for customers to manage their Apple hardware
+- sell the system separately to service providers who don't need/want Servo
+
+Checkin should have 3 possible backend choices:
+- Email (just dump all the entered text into an email)
+- HTTP post (JSON, authenticated)
+- Servo
+
+
+The Servo backend
+=================
+- Associate the customer with a Servo customer with their email address (?)
+- Create the Service Order
+- Add the customer's notes (by the API user)
+- Update the service order with input from the customer duing the repair
+- The customer can print the work confirmation
+- The Service Provider gets a custom URL (http://checkin.servoapp.com/provider)
+
+
+The Implementation
+==================
+- Django app
+- PostgreSQL
+- south
+- Use as many generic class-based views as possible
+- Bootstrap 3
+- warranty checkup through py-gsxws
+- Desktop, phone, tablet
+
+
+Checkin Admin
+=============
+- Create AASP accounts (backend, urls, etc)
+- Show some customer stats? (no. of logins...)
diff --git a/apps/checkin/__init__.py b/apps/checkin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/checkin/__init__.py
diff --git a/apps/checkin/checkin.mindnode/QuickLook/Preview.jpg b/apps/checkin/checkin.mindnode/QuickLook/Preview.jpg
new file mode 100644
index 0000000..3a33372
--- /dev/null
+++ b/apps/checkin/checkin.mindnode/QuickLook/Preview.jpg
Binary files differ
diff --git a/apps/checkin/checkin.mindnode/contents.xml b/apps/checkin/checkin.mindnode/contents.xml
new file mode 100644
index 0000000..3171723
--- /dev/null
+++ b/apps/checkin/checkin.mindnode/contents.xml
@@ -0,0 +1,1507 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>author</key>
+ <string></string>
+ <key>comments</key>
+ <string></string>
+ <key>isUsingConstrainedLayout</key>
+ <false/>
+ <key>keywords</key>
+ <string></string>
+ <key>mindMap</key>
+ <dict>
+ <key>associations</key>
+ <array>
+ <dict>
+ <key>endArrow</key>
+ <integer>1</integer>
+ <key>endNodeID</key>
+ <string>B9D3B1E4-B44D-4A49-87CC-852937542677</string>
+ <key>startArrow</key>
+ <integer>0</integer>
+ <key>startNodeID</key>
+ <string>2CFCCC66-C66B-44BB-85B1-88EE7CDCC9C0</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.500, 1.000, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>1</integer>
+ <key>strokeWidth</key>
+ <real>1</real>
+ <key>wayPointOffset</key>
+ <string>{-96.6797, 157.84}</string>
+ </dict>
+ </array>
+ <key>color</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>mainNodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <true/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{-296.22585227272691, -190.51065340909088}</string>
+ <key>nodeID</key>
+ <string>C199C0FB-BE46-4F21-919A-D1760AC07432</string>
+ <key>strokeColor</key>
+ <string>{0.500, 0.500, 0.500, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>2</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{-31.132102272726911, -426.63174715909088}</string>
+ <key>nodeID</key>
+ <string>DB60DB17-ABB4-41F1-A5E8-2AE2E9EDB286</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>6</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{130.92968750000034, -637.74325284090924}</string>
+ <key>nodeID</key>
+ <string>55AA61F0-0A63-44FB-900D-1587F471E3B9</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -765.74325284090924}</string>
+ <key>nodeID</key>
+ <string>0AEE735E-431C-427E-9C71-1A79BD2E5FFC</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;first name&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 first name}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -733.74325284090924}</string>
+ <key>nodeID</key>
+ <string>963D451B-1670-44D6-A8C5-E2D476424939</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;last name&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 last name}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -701.74325284090924}</string>
+ <key>nodeID</key>
+ <string>C9938290-7D28-4AF2-A56E-5CB3DFB2B05D</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;company&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 company}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -669.74325284090924}</string>
+ <key>nodeID</key>
+ <string>B6BE8DC1-3C39-44B3-AF13-015809F88E27</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;email&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 email}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -637.74325284090924}</string>
+ <key>nodeID</key>
+ <string>F4CB2543-5ACD-4839-B909-BFA27AC5CF26</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;phone&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 phone}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -605.74325284090924}</string>
+ <key>nodeID</key>
+ <string>E2D4CAA1-4EC0-4902-AF2D-CBBBE81F28F5</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;address&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 address}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -573.74325284090924}</string>
+ <key>nodeID</key>
+ <string>096A67F4-1240-4545-A069-848CD7FE2A35</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;zip code&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 zip code}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -541.74325284090924}</string>
+ <key>nodeID</key>
+ <string>BB7C71F6-C57F-4F7E-9F41-1E09C33077D7</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;city&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 city}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{242.92968750000034, -509.74325284090924}</string>
+ <key>nodeID</key>
+ <string>00832BCE-D6D2-4C1B-A9B9-4E7B26D0CC4F</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;password&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 password}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;fields&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 fields}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{99.867897727273089, -378.63174715909088}</string>
+ <key>nodeID</key>
+ <string>B9A64567-58AE-4728-80AB-CB4135511C7B</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{219.86789772727309, -442.63174715909088}</string>
+ <key>nodeID</key>
+ <string>A0411427-08C3-4112-B0E6-FC7DE25E7310</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;model&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 model}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{219.86789772727309, -410.63174715909088}</string>
+ <key>nodeID</key>
+ <string>59971B68-93AA-41EB-A6D1-B131675137CA</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;configuration&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 configuration}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{219.86789772727309, -378.63174715909088}</string>
+ <key>nodeID</key>
+ <string>44E4FF78-B308-41F7-ABF7-510366694717</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;pop&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 pop}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{219.86789772727309, -346.63174715909088}</string>
+ <key>nodeID</key>
+ <string>1FF5714A-255B-4063-A7E2-51AF2111499D</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;username&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 username}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{219.86789772727309, -314.63174715909088}</string>
+ <key>nodeID</key>
+ <string>E6C6A9F0-B6A7-4B5B-AFE9-1C6D4F8063E6</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;password&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 password}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;devices&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 devices}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{99.867897727273089, -218.63174715909088}</string>
+ <key>nodeID</key>
+ <string>E6AC23C3-9AC2-4E39-A588-B38BB9770809</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{249.86789772727309, -282.63174715909088}</string>
+ <key>nodeID</key>
+ <string>BE72CAFD-3DF8-49B0-BB3E-BA9BAAB2957A</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;problem&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 problem}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{249.86789772727309, -250.63174715909088}</string>
+ <key>nodeID</key>
+ <string>058C266C-5DD5-433C-9D9E-6379801193AA</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{361.86789772727309, -250.63174715909088}</string>
+ <key>nodeID</key>
+ <string>BD5A5DC2-3BC1-4491-819E-BE54D514C4A5</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>3</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;attachments&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 attachments}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;notes&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 notes}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{249.86789772727309, -218.63174715909088}</string>
+ <key>nodeID</key>
+ <string>5468F5DB-6F82-4A74-997C-47E4D48A97B8</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;status&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 status}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{249.86789772727309, -186.63174715909088}</string>
+ <key>nodeID</key>
+ <string>3218C3C2-7862-4731-8B56-433A16E93FFB</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;rating&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 rating}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{249.86789772727309, -154.63174715909088}</string>
+ <key>nodeID</key>
+ <string>2CFCCC66-C66B-44BB-85B1-88EE7CDCC9C0</string>
+ <key>strokeColor</key>
+ <string>{0.467, 0.000, 0.851, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;service provider&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 service provider}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;service case&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 service case}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;customer&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 customer}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{56.508522727273089, 161.04794034090912}</string>
+ <key>nodeID</key>
+ <string>B9D3B1E4-B44D-4A49-87CC-852937542677</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.608, 0.847, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>6</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{228.50852272727309, 145.04794034090912}</string>
+ <key>nodeID</key>
+ <string>7726D723-5B52-4CD6-BCA0-8648E437D1A3</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.608, 0.847, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;backend type&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 backend type}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <false/>
+ <key>location</key>
+ <string>{228.50852272727309, 177.04794034090912}</string>
+ <key>nodeID</key>
+ <string>3FC8C8A7-54DE-45F6-A66A-6E34AB6954FF</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.608, 0.847, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;servo url&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 servo url}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;service provider&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 service provider}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-466.22585227272691, -99.510653409090878}</string>
+ <key>nodeID</key>
+ <string>4F122D04-DAE9-422F-9D22-807F6F8AD928</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>6</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-710.22585227272691, -179.51065340909088}</string>
+ <key>nodeID</key>
+ <string>C1C503FA-E1E1-4EAB-8CB4-3C60710CED4A</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Does the device power on?&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Does the device power on?}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-825.22585227272691, -147.51065340909088}</string>
+ <key>nodeID</key>
+ <string>0C3E1E6A-57AE-4B07-BF21-CE2CC6509E4B</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Was the issue caused by accidental damage?&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Was the issue caused by accidental damage?}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-809.22585227272691, -115.51065340909088}</string>
+ <key>nodeID</key>
+ <string>C15860CD-ED20-436D-ABC0-CE5EA4177623</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Do you have a recent backup of your data?&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Do you have a recent backup of your data?}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-764.22585227272691, -51.510653409090878}</string>
+ <key>nodeID</key>
+ <string>E3D0D683-B76B-4BBE-BC4A-1E4D7EEA5C94</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>5</real>
+ <key>subnodes</key>
+ <array>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-904.22585227272691, -83.510653409090878}</string>
+ <key>nodeID</key>
+ <string>DF33303C-54EC-449E-996A-8E2222F263E0</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Constantly&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Constantly}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-972.22585227272691, -51.510653409090878}</string>
+ <key>nodeID</key>
+ <string>8C45AA5C-F770-4F73-996A-2B7F394F6F08</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Several times per day&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Several times per day}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>contentAlignment</key>
+ <integer>1</integer>
+ <key>fillColor</key>
+ <string>{1.000, 1.000, 1.000, 1.000}</string>
+ <key>isDecreasingBranchThickness</key>
+ <true/>
+ <key>isDrawingFill</key>
+ <false/>
+ <key>isLeftAligned</key>
+ <true/>
+ <key>location</key>
+ <string>{-982.22585227272691, -19.510653409090878}</string>
+ <key>nodeID</key>
+ <string>B961D71E-AF99-4BDB-8ED0-EB6D0C840A0E</string>
+ <key>strokeColor</key>
+ <string>{0.000, 0.851, 0.671, 1.000}</string>
+ <key>strokeStyle</key>
+ <integer>0</integer>
+ <key>strokeWidth</key>
+ <real>4</real>
+ <key>subnodes</key>
+ <array/>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Several times per week&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Several times per week}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;How often does the problem occur?&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 How often does the problem occur?}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;troubleshooting&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 troubleshooting}</string>
+ </dict>
+ </dict>
+ </array>
+ <key>title</key>
+ <dict>
+ <key>constrainedWidth</key>
+ <integer>300</integer>
+ <key>htmlText</key>
+ <string>&lt;p style='color: rgba(0, 0, 0, 1.000000); font: 14px "Helvetica Neue"; -cocoa-font-postscriptname: "HelveticaNeue"; '&gt;Checkin&lt;/p&gt;</string>
+ <key>shrinkToFitContent</key>
+ <integer>1</integer>
+ <key>text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265
+{\fonttbl\f0\fnil\fcharset0 HelveticaNeue;}
+{\colortbl;\red255\green255\blue255;\red0\green0\blue0;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
+
+\f0\fs28 \cf2 Checkin}</string>
+ </dict>
+ </dict>
+ </array>
+ </dict>
+ <key>printInfo</key>
+ <data>
+ BAtzdHJlYW10eXBlZIHoA4QBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE
+ hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpCJKEhIQITlNT
+ dHJpbmcBlIQBKxZOU0hvcml6b250YWxseUNlbnRlcmVkhpKEhIQITlNOdW1iZXIAhIQH
+ TlNWYWx1ZQCUhAEqhIQBY50BhpKEmZkNTlNSaWdodE1hcmdpboaShJuchIQBZp5IhpKE
+ mZkMTlNMZWZ0TWFyZ2luhpKEm5ygnkiGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26G
+ koSbnISXlwKGkoSZmRROU1ZlcnRpY2FsUGFnaW5hdGlvboaShJucpZcAhpKEmZkUTlNW
+ ZXJ0aWNhbGx5Q2VudGVyZWSGkpqShJmZC05TVG9wTWFyZ2luhpKEm5ygnlqGkoSZmQ5O
+ U0JvdHRvbU1hcmdpboaShJucoJ5ahoaG
+ </data>
+ <key>title</key>
+ <string>checkin</string>
+ <key>version</key>
+ <integer>4</integer>
+</dict>
+</plist>
diff --git a/apps/checkin/checkin.mindnode/style.mindnodestyle/contents.xml b/apps/checkin/checkin.mindnode/style.mindnodestyle/contents.xml
new file mode 100644
index 0000000..7904eba
--- /dev/null
+++ b/apps/checkin/checkin.mindnode/style.mindnodestyle/contents.xml
Binary files differ
diff --git a/apps/checkin/checkin.mindnode/style.mindnodestyle/metadata.plist b/apps/checkin/checkin.mindnode/style.mindnodestyle/metadata.plist
new file mode 100644
index 0000000..5cb6e90
--- /dev/null
+++ b/apps/checkin/checkin.mindnode/style.mindnodestyle/metadata.plist
Binary files differ
diff --git a/apps/checkin/checkin.mindnode/viewState.plist b/apps/checkin/checkin.mindnode/viewState.plist
new file mode 100644
index 0000000..b5098a5
--- /dev/null
+++ b/apps/checkin/checkin.mindnode/viewState.plist
Binary files differ
diff --git a/apps/checkin/models.py b/apps/checkin/models.py
new file mode 100644
index 0000000..efea6ff
--- /dev/null
+++ b/apps/checkin/models.py
@@ -0,0 +1,94 @@
+import uuid
+from django.db import models
+from django.conf import settings
+from django.utils.translation import ugettext as _
+
+from apps.core.models import TaggedItem, ServiceProvider
+
+
+class Device(models.Model):
+ sn = models.CharField(
+ blank=True,
+ default='',
+ max_length=32,
+ verbose_name=_("Serial Number")
+ )
+ description = models.CharField(
+ max_length=128,
+ default=_("New Device"),
+ verbose_name=_("description")
+ )
+ WARRANTY_CHOICES = (
+ ('ALW', _("Apple Limited Warranty")),
+ ('APP', _("AppleCare Protection Plan")),
+ ('CSC', _("Customer Satisfaction (CS) Code")),
+ ('CBC', _("Custom Bid Contracts")),
+ ('WTY', _("3'rd Party Warranty")),
+ ('OOW', _("Out Of Warranty (No Coverage)")),
+ ('NA', _("Unknown")),
+ )
+
+ warranty_status = models.CharField(
+ max_length=3,
+ default="NA",
+ choices=WARRANTY_CHOICES,
+ verbose_name=_("Warranty Status")
+ )
+ username = models.CharField(
+ blank=True,
+ default='',
+ max_length=32,
+ verbose_name=_("username")
+ )
+ password = models.CharField(
+ blank=True,
+ default='',
+ max_length=32,
+ verbose_name=_("password")
+ )
+
+
+class Customer(models.Model):
+ sp = models.ForeignKey(ServiceProvider)
+ user = models.ForeignKey(settings.AUTH_USER_MODEL)
+ street_address = models.CharField(
+ null=True,
+ blank=True,
+ max_length=128,
+ verbose_name=_('address')
+ )
+ zip_code = models.CharField(
+ null=True,
+ blank=True,
+ max_length=32,
+ verbose_name=_('ZIP Code')
+ )
+ city = models.CharField(
+ null=True,
+ blank=True,
+ max_length=32,
+ verbose_name=_('city')
+ )
+ devices = models.ManyToManyField(Device, null=True)
+
+
+class ServiceOrder(models.Model):
+ sp = models.ForeignKey(ServiceProvider)
+ uuid = models.CharField(
+ max_length=36,
+ unique=True,
+ default=lambda: str(uuid.uuid4())
+ )
+ created_by = models.ForeignKey(settings.AUTH_USER_MODEL)
+ notes = models.TextField(default='')
+ customer = models.ForeignKey(Customer)
+ devices = models.ManyToManyField(Device, null=True)
+ tags = models.ManyToManyField(TaggedItem)
+
+ def add_accessory(self, accessory):
+ tag = TaggedItem()
+ tag.kind = 'accessory'
+ tag.save()
+
+ def submit(self):
+ pass
diff --git a/apps/checkin/tests.py b/apps/checkin/tests.py
new file mode 100644
index 0000000..501deb7
--- /dev/null
+++ b/apps/checkin/tests.py
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.assertEqual(1 + 1, 2)
diff --git a/apps/checkin/views.py b/apps/checkin/views.py
new file mode 100644
index 0000000..60f00ef
--- /dev/null
+++ b/apps/checkin/views.py
@@ -0,0 +1 @@
+# Create your views here.
diff --git a/apps/core/__init__.py b/apps/core/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/core/__init__.py
diff --git a/apps/core/admin.py b/apps/core/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/apps/core/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/apps/core/forms.py b/apps/core/forms.py
new file mode 100644
index 0000000..66a6287
--- /dev/null
+++ b/apps/core/forms.py
@@ -0,0 +1,12 @@
+from django import forms
+
+
+class LoginForm(forms.Form):
+ username = forms.CharField(widget=forms.TextInput(attrs={
+ 'class': 'form-control',
+ 'placeholder': 'Email address'
+ }))
+ password = forms.CharField(widget=forms.PasswordInput(attrs={
+ 'class': 'form-control',
+ 'placeholder': 'password'
+ }))
diff --git a/apps/core/models.py b/apps/core/models.py
new file mode 100644
index 0000000..04d7582
--- /dev/null
+++ b/apps/core/models.py
@@ -0,0 +1,59 @@
+import uuid
+from django.db import models
+from django.contrib.contenttypes import generic
+from django.contrib.auth.models import AbstractUser
+from django.contrib.contenttypes.models import ContentType
+
+from django.template.defaultfilters import slugify
+
+
+class ServiceProvider(models.Model):
+ uuid = models.CharField(
+ unique=True,
+ max_length=36,
+ default=lambda: str(uuid.uuid4())
+ )
+ BACKEND_CHOICES = (
+ ('http', 'HTTP'),
+ ('smtp', 'SMTP'),
+ ('servo', 'Servo')
+ )
+ backend_type = models.CharField(
+ max_length=6,
+ default='servo',
+ choices=BACKEND_CHOICES
+ )
+ name = models.CharField(
+ max_length=128,
+ default='Apple Service Provider'
+ )
+ http_url = models.URLField(null=True, blank=True)
+ http_username = models.CharField(max_length=128, null=True, blank=True)
+ http_password = models.CharField(max_length=128, null=True, blank=True)
+ smtp_address = models.EmailField(null=True, blank=True)
+ servo_url = models.URLField(null=True, blank=True)
+
+
+class User(AbstractUser):
+ sp = models.ForeignKey(ServiceProvider, null=True)
+
+
+class TaggedItem(models.Model):
+ "A generic tagged item"
+ tag = models.CharField(max_length=128)
+ slug = models.SlugField()
+ kind = models.CharField(max_length=64, default='')
+
+ object_id = models.PositiveIntegerField()
+ content_type = models.ForeignKey(ContentType)
+ content_object = generic.GenericForeignKey("content_type", "object_id")
+
+ def save(self, *args, **kwargs):
+ self.slug = slugify(self.tag)
+ super(TaggedItem, self).save(*args, **kwargs)
+
+ def __unicode__(self):
+ return self.tag
+
+ class Meta:
+ unique_together = ("content_type", "object_id", "tag",)
diff --git a/apps/core/templates/login.html b/apps/core/templates/login.html
new file mode 100644
index 0000000..5f53b32
--- /dev/null
+++ b/apps/core/templates/login.html
@@ -0,0 +1,2 @@
+{% extends 'default.html' %}
+
diff --git a/apps/core/tests.py b/apps/core/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/apps/core/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/apps/core/views.py b/apps/core/views.py
new file mode 100644
index 0000000..fc8f941
--- /dev/null
+++ b/apps/core/views.py
@@ -0,0 +1,17 @@
+from django.shortcuts import render
+from django.views.generic.edit import FormView
+from django.views.generic.list import ListView
+from apps.core.forms import LoginForm
+
+from apps.core.models import ServiceProvider
+
+
+class LoginView(FormView):
+ template_name = 'login.html'
+ form_class = LoginForm
+ success_url = '/manage/sites/'
+
+
+class SitesListView(ListView):
+ model = ServiceProvider
+ template_name = 'manage/sites.html'
diff --git a/apps/docs/__init__.py b/apps/docs/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/docs/__init__.py
diff --git a/apps/docs/admin.py b/apps/docs/admin.py
new file mode 100644
index 0000000..4902ccc
--- /dev/null
+++ b/apps/docs/admin.py
@@ -0,0 +1,5 @@
+from django.contrib import admin
+from docs.models import Article, Image
+
+admin.site.register(Article)
+admin.site.register(Image)
diff --git a/apps/docs/models.py b/apps/docs/models.py
new file mode 100644
index 0000000..bd95207
--- /dev/null
+++ b/apps/docs/models.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from django.db import models
+from django.template.defaultfilters import slugify
+
+
+class Image(models.Model):
+ image = models.ImageField(upload_to='media/images')
+ title = models.CharField(max_length=128, null=True)
+
+
+class Article(models.Model):
+ slug = models.SlugField(editable=False)
+ title = models.CharField(max_length=255)
+ content = models.TextField()
+ published = models.BooleanField(default=True)
+ created_at = models.DateTimeField(auto_now=True)
+ updated_at = models.DateTimeField(auto_now=True)
+
+ images = models.ManyToManyField(Image, null=True)
+
+ def __unicode__(self):
+ return self.title
+
+ def save(self, *args, **kwargs):
+ self.slug = slugify(self.title)
+ super(Article, self).save(*args, **kwargs)
diff --git a/apps/docs/templates/default.html b/apps/docs/templates/default.html
new file mode 100644
index 0000000..9446a3d
--- /dev/null
+++ b/apps/docs/templates/default.html
@@ -0,0 +1,78 @@
+{% load staticfiles %}
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>{{ title }}</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <!-- Bootstrap -->
+ <link href="{{ STATIC_URL }}bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
+ <style type="text/css">
+ body {
+ padding-top: 60px;
+ padding-bottom: 40px;
+ }
+ .terms li, .terms dd {
+ margin-bottom: 20px;
+ }
+ .terms h3 {
+ margin-top: 20px;
+ }
+ .terms hr {
+ margin-top: 10px;
+ }
+ .sidebar-nav {
+ padding: 9px 0;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="navbar navbar-inverse navbar-fixed-top">
+ <div class="navbar-inner">
+ <div class="container-fluid">
+ <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="brand" href="/">ServoApp Help</a>
+ </div>
+ </div>
+ </div>
+
+ <div class="container-fluid">
+ <div class="row-fluid">
+ {% block content %}
+ <div class="span3">
+ <div class="well sidebar-nav">
+ <ul class="nav nav-list">
+ <li class="nav-header">Topics</li>
+ {% for i in topics %}
+ <li><a href="{% url 'docs-view' i.slug %}">{{ i.title }}</a></li>
+ {% endfor %}
+ {% block sidebar %}
+ {% endblock sidebar %}
+ </ul>
+ </div>
+ </div>
+ <div class="span9">
+ {% block main %}
+ {% endblock main %}
+ </div>
+ {% endblock content %}
+ </div>
+ <hr/>
+ <footer>
+ <p>&copy; {% now "Y" %} First Party Software <span class="pull-right"><a href="/terms/">Terms of Service</a></span></p>
+ </footer>
+ </div>
+ <script src="{{ STATIC_URL }}js/jquery.min.js"></script>
+ <script src="{{ STATIC_URL }}bootstrap/js/bootstrap.min.js"></script>
+ <script type="text/javascript">
+ $(function(){
+ // highlight the current article
+ var loc = location.pathname.split("/")[1];
+ $('.sidebar-nav a[href*="' + loc + '"]').parent().addClass('active');
+ });
+ </script>
+ </body>
+</html>
diff --git a/apps/docs/templates/docs_index.html b/apps/docs/templates/docs_index.html
new file mode 100644
index 0000000..e692368
--- /dev/null
+++ b/apps/docs/templates/docs_index.html
@@ -0,0 +1,8 @@
+{% extends "default.html" %}
+{% load staticfiles %}
+{% block main %}
+<div class="container-fluid text-center">
+ <img src="{{ STATIC_URL }}img/servo-logo-large.gif" alt="Servo" class="text-center"/>
+</div>
+
+{% endblock main %}
diff --git a/apps/docs/templates/docs_view.html b/apps/docs/templates/docs_view.html
new file mode 100644
index 0000000..54a4fc0
--- /dev/null
+++ b/apps/docs/templates/docs_view.html
@@ -0,0 +1,8 @@
+{% extends "default.html" %}
+{% load motor_tags %}
+
+{% block main %}
+ <small class="muted pull-right">Last updated: {{ article.updated_at|date:"SHORT_DATE_FORMAT" }}</small>
+ <h2>{{ article.title }}</h2>
+ {{ article.content|markdown }}
+{% endblock main %}
diff --git a/apps/docs/templates/terms.html b/apps/docs/templates/terms.html
new file mode 100644
index 0000000..847046a
--- /dev/null
+++ b/apps/docs/templates/terms.html
@@ -0,0 +1,256 @@
+{% extends "default.html" %}
+{% block content %}
+
+<div class="terms">
+ <h2>{{ title }}</h2>
+
+ <p>By using the ServoApp Service Management System ("Service"), or any services of First Party Software, Ltd (" First Part Software"), you are agreeing to be bound by the following terms and conditions ("Terms of Service").</p>
+
+ <p>IF YOU ARE ENTERING INTO THIS AGREEMENT ON BEHALF OF A COMPANY OR OTHER LEGAL ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND SUCH ENTITY, ITS AFFILIATES AND ALL USERS WHO ACCESS OUR SERVICES THROUGH YOUR ACCOUNT TO THESE TERMS AND CONDITIONS, IN WHICH CASE THE TERMS "YOU" OR "YOUR" SHALL REFER TO SUCH ENTITY, ITS AFFILIATES AND USERS ASSOCIATED WITH IT. IF YOU DO NOT HAVE SUCH AUTHORITY, OR IF YOU DO NOT AGREE WITH THESE TERMS AND CONDITIONS, YOU MUST NOT ACCEPT THIS AGREEMENT AND MAY NOT USE THE SERVICES.</p>
+
+ <p>If First Party Software makes material changes to these Terms, we will notify you by email or by posting a notice on our site before the changes are effective. Any new features that augment or enhance the current Service, including the release of new tools and resources, shall be subject to the Terms of Service. Continued use of the Service after any such changes shall constitute your consent to such changes. You can review the most current version of the Terms of Service at any time at: <a href="https://docs.servoapp.com/terms/">https://docs.servoapp.com/terms/.</a></p>
+
+ <h3>A. Definition of Terms</h3>
+ <hr/>
+ <dl class="dl-horizontal">
+ <dt>"Agreement"</dt>
+ <dd>These terms of service (as amended from time to time), the terms appearing on the Sign-up Form and any other terms regarding the Service that the Customer may agree to when prompted to by the Supplier.</dd>
+
+ <dt>"Supplier"</dt>
+ <dd>First Party Software Ltd., a company incorporated under the laws of Estonia, seated in Kadaka tee 137-50, Tallinn 12915, company no 12481447.</dd>
+
+ <dt>"Content"</dt>
+ <dd>The information (including text, images, audio and video material), functionality, technical resources, Supplier’s time and attention and Service availability provided by the Supplier.</dd>
+
+ <dt>"Customer"</dt>
+ <dd>Any person or entity subscribed to the Service.</dd>
+
+ <dt>"End User"</dt>
+ <dd>Any natural person that the Customer permits or causes to have access to the Service.</dd>
+
+ <dt>"Intellectual Property"</dt>
+ <dd>All existing and future trademarks, service marks, domain names and business names, rights pertaining to inventions, designs, databases and proprietary information (including, without limitation, trade secrets and know-how), copyrights, moral rights and all other assets and benefits commonly regarded as intellectual property, whether registered or not.</dd>
+
+ <dt>"Party"</dt>
+ <dd>A common term for each of the Customer and the Supplier.</dd>
+
+ <dt>"Registration Data"</dt>
+ <dd>The information provided by the Customer when subscribing to the Service, requesting a change of their Service or filling in forms via the Service, including the Customer’s full name or business name, registration/company/file/business or personal identification number (or equivalent), place of domicile, address, email address, phone number and such other information as the Supplier reasonably may request from the Customer.</dd>
+
+ <dt>"Service"</dt>
+ <dd>The Software, provided “as a service” (SaaS) through this website, the availability of Content and customer support.</dd>
+
+ <dt>"Sign-up Form"</dt>
+ <dd>The online form available on this website for subscribing the Customer to the Service or requesting a change, or such other subscription or modification form as the Parties may execute for the aforesaid purpose.</dd>
+
+ <dt>"Software"</dt>
+ <dd>The service software applications included in the Service with features as described on this website, including such modifications and replacements thereof as the Supplier or the Company in their sole discretion may from time to time provide.</dd>
+
+ <dt>"User Account"</dt>
+ <dd>A Supplier-hosted or -administered account provided to the Customer through the Service for the purpose of enabling such Customer to use the Service.</dd>
+ </dl>
+
+ <ol>
+ <li>“Herein”, “hereto”, “hereof”, “hereunder” and similar expressions, wherever used in this Agreement, shall be deemed to refer to the Agreement.</li>
+
+ <li>This Agreement in its current version and the information published on this website, in so far as it describes the Service and prices, constitute the whole agreement between the Parties relating to the subject matter hereof and supersede all prior agreements, arrangements and understandings between the Parties relating to that subject matter.</li>
+
+ <li>In case of conflict or ambiguity between any provision contained herein and any statement, representation or other information published on this website, the provision in the Agreement shall prevail.</li>
+ </ol>
+
+ <h3>B. Term</h3>
+ <hr/>
+ <ol>
+ <li>This Agreement shall be effective between the Parties as of the moment when the Customer is subscribed to the Service or obtains a User Account or starts using the Service, whichever is the earliest. The Agreement is entered into for an indefinite term and may be cancelled by either Party as provided herein.</li>
+ </ol>
+
+ <h3>C. License</h3>
+ <hr/>
+ <ol>
+ <li>Relying on the Customer’s Registration Data and subject to the terms set forth herein, the Supplier grants to the Customer, and the latter accepts, a limited, non-exclusive and non-transferable license to use the Software and Content.</li>
+
+ <li>The Software and the Content may only be used in such manner as necessary for utilising the Service for its intended purpose and only during the time that the Agreement is in force between the Parties. The Customer acknowledges that they have no right to have access to the Software in source code form or in unlocked coding or with comments.</li>
+
+ <li>With respect to assignment and sub-licensing, the Parties have agreed that (i) the Customer has no right to sub-license or assign the benefit or burden of this Agreement (in whole or in part) and shall not allow the Software or any other part of the Service to become the subject of any charge, lien or encumbrance without the prior explicit consent of the Supplier; (ii) the Supplier may sub-license, assign, charge and otherwise dispose of its rights and obligations hereunder, provided it gives the Customer reasonable notice thereof of no less than 3 months.</li>
+
+ <li>The Supplier houses the Software on its own or rented resources.</li>
+ </ol>
+
+ <h3>D. Service</h3>
+ <hr/>
+ <ol>
+ <li>The Supplier will use commercially reasonable efforts to provide the Service to the Customer throughout the term of the Agreement.</li>
+
+ <li>The Customer acknowledges that (i) the Service has not been designed to meet their individual requirements; (ii) the operation of the Service may from time to time encounter technical or other problems and may not necessarily continue uninterrupted or without errors; (iii) the results that may be obtained from the use of the service will be accurate or reliable, (iv) the quality of any products, services, information, or other material purchased or obtained by you through the service will meet your expectations, and (v) any errors in the Service will be corrected.</li>
+
+ <li>The Supplier is committed to providing excellent customer service, and aims to answer most support issues as soon as possible. However, the Supplier makes no guarantee on the period of time before support is provided.</li>
+
+ <li>The Service (including all Software and Content) is provided on an “as is” and “as available” basis.</li>
+
+ <li>The Customer’s selection and use of the Service is at the Customer’s own risk.</li>
+
+ <li>The Supplier has no obligation to enhance, modify or replace any part of the Service or to continue developing or releasing new versions thereof.</li>
+ </ol>
+
+ <h3>E. Payment</h3>
+ <hr/>
+ <ol>
+ <li>The Customer acknowledges that by subscribing to the Service they agree to such fees, rates and billing cycles associated therewith as (i) described on this website at the time of subscription and (ii) amended from time to time pursuant to the terms of the Agreement.</li>
+
+ <li>Unless otherwise agreed at the time of subscription, the Customer’s billing cycle is 30 days, starting on the day immediately following their subscription to the the Service through the website, or, if a free trial period has been granted to the Customer, on the day immediately following the expiry of the trial period.</li>
+
+ <li>The Supplier may enhance or otherwise modify the Service for additional fees, and, upon a 30 days’ prior notice, may modify the fees, rates and the billing cycle applicable under the Agreement. In the event that the Customer does not agree with the respective modification(s), their sole and exclusive remedy shall be to unsubscribe from the Service, terminating their use of the Service.</li>
+
+ <li>Payment for the Service is due in advance by the first day of each billing cycle, and shall be made either by wire transfer or credit card or, where available, by ACH transfer. The Customer acknowledges that late payment may result in the suspension of Service or cancellation of the Agreement.</li>
+
+ <li>Should the Customer unsubscribe from the Service or the Service be modified or the Agreement be terminated prior to the end of the then-current billing cycle, no refund will be given to the Customer for any payment relating to that billing cycle.</li>
+
+ <li>Prepayments for future billing cycles are non-refundable.</li>
+
+ <li>All fees and rates are exclusive of value added tax, sales tax and other public burdens. The Customer shall be solely responsible for all taxes and other burdens that may be levied on the Customer’s purchase or use of the Service.</li>
+ </ol>
+
+ <h3>F. Customer undertaking</h3>
+ <hr/>
+ <ol>
+ <li>The Customer must be a person (either natural or legal), or an entity with legal capacity.</li>
+
+ <li>All Registration Data provided by the Customer must be true, accurate and up-to-date and the Customer undertakes to promptly correct any Registration Data that becomes outdated or incorrect. The Supplier is entitled but not obliged to verify the Customer’s Registration Data and may rely on this data without any verification.</li>
+
+ <li>The Customer must comply with all laws, regulations and ordinances applicable to the Customer’s use of the Service.</li>
+
+ <li>With respect to the information (including all text, images, audiovisual material and other content) that the Customer uploads, transmits or stores via the Service, the Customer represents and warrants to the Supplier, that the Customer has the right to upload, transmit and store the same.</li>
+
+ <li>The Customer shall not, and shall cause the End Users not to, use the Service for sending unsolicited communications or for uploading, transmitting, delivering, running or storing harmful code, malware or illegal content.</li>
+
+ <li>Any Customer content that conflicts with the provisions of this Agreement may be removed, disabled and/or destroyed by the Supplier at their sole discretion without any warning or notice.</li>
+
+ <li>Without excluding or limiting any of the Customer’s statutory obligations, the Customer undertakes to the Supplier that the Customer will not, and will not allow any End User to (i) modify, reproduce or prepare derivative works from, or decompile, reverse engineer or otherwise attempt to derive source code from the Software or any other part of the Service; (ii) remove, alter, hide or obscure any copyright notice, trademark or other proprietary rights notice embedded in, appearing on or otherwise pertaining to the Service; (iii) create or attempt to create any product or service that is similar or otherwise competitive to the Service or purporting to be created, provided or approved by the Supplier.</li>
+ </ol>
+
+ <h3>G. Representative’s undertaking</h3>
+ <hr/>
+ <ol>
+ <li>Each person subscribing the Customer to the Service or otherwise representing the Customer upon the latter’s entry into the Agreement personally warrants to the Supplier that s/he has the authority to act on the Customer’s behalf and that the Agreement is binding upon the Customer.</li>
+
+ <li>Each such representative hereby personally undertakes to the Supplier, and the latter agrees, that if this Agreement proves to be void due to the representative’s lack or excess of authority or if it emerges that the representative has concluded the Agreement on behalf of a non-existent Customer then such representative shall be deemed to have entered into the Agreement on his/her own behalf and the Agreement shall be effective (ab initio) between the Supplier and the aforesaid representative.</li>
+ </ol>
+  
+ <h3>H. User Account, username and password</h3>
+ <hr/>
+ <ol>
+ <li>The Customer shall be solely and entirely responsible for the activity that occurs under their User Account, and must notify the Supplier immediately of any breach of security relating to, or unauthorised use of, such User Account.</li>
+
+ <li>With respect to the Customer’s username and password, the Parties have agreed that the Customer shall be responsible for (i) maintaining the confidentiality of their username and password, (ii) any and all actions by persons that the Customer gives access to or that otherwise use such username or password, and (iii) any and all consequences of use or misuse of such username or password.</li>
+
+ <li>Neither the Supplier nor the Company shall be responsible for any loss, damage or other consequences that may result from any unauthorised use of the Customer’s User Account, username or password.</li>
+ </ol>
+
+ <h3>I. Intellectual property and proprietary rights</h3>
+ <hr/>
+ <ol>
+ <li>The Supplier does not claim any intellectual property rights over the material the Customer provides to the Service. Your service data and materials uploaded remain yours.</li>
+
+ <li>The Customer acknowledges that all Service-related Intellectual Property belongs and shall belong to the Supplier. The Customer shall not acquire any right, title, or interest in the aforesaid Intellectual Property or otherwise in connection with the Service, except for the limited rights of use expressly set forth in the Agreement. Any rights not expressly granted herein shall be deemed withheld.</li>
+
+ <li>Neither the fact of concluding this Agreement, nor any provision contained herein, nor any breach by any Party of its obligations hereunder, shall be construed as creating in the Customer or cause the Customer to acquire any proprietary right, security interest, pawn or any other right of security with respect to any item or asset belonging to the Supplier.</li>
+
+ <li>The Supplier respects the Intellectual Property of others and may, in appropriate circumstances and at its discretion, disable or terminate any User Account through which the rights of others are infringed.</li>
+ </ol>
+
+ <h3>J. Disclaimer of Warranties</h3>
+ <hr/>
+ <ol>
+ <li>All conditions, representations and warranties not expressly stated herein (including, without limitation, those relating to merchantability, fitness for a particular purpose and non-infringement, and those that may arise from a course of performance, course of dealing or usage of trade) shall be deemed withheld by the Supplier to the fullest extent permitted.</li>
+
+ <li>The Supplier will not make any representation or warranty (i) that the Service will meet the Customer’s or the End Users’ requirements or expectations, (ii) that access to or use of the Service will be uninterrupted, timely, secure or error-free, (iii) that any defects in the Service will be corrected, (iv) that the Service or any means by which the Service is accessed is free of malware or other harmful components; or (v) with respect to any third-party software, content, material, information, infrastructure or other third-party resources or services that the Customer or any End User may acquire, use, access or be exposed to through or due to the Service.</li>
+
+ <li>Each Party acknowledges that the other Party has entered into the Agreement relying on the above disclaimers and that the aforesaid disclaimers are an essential basis of the bargain between the Parties.</li>
+ </ol>
+
+ <h3>K. Limitation of liability</h3>
+ <hr/>
+ <ol>
+ <li>The Supplier will not be liable to the Customer, any End User or any person claiming under or through the Customer or an End User for any loss, damage, expenses or other consequences resulting from (i) the use or the inability to use the Service, (ii) the properties of the Service, (iii) the need to procure or the procurement of substitute goods or services for the Service or for any item, service or other benefit received, owned, possessed or otherwise enjoyed through the Service, (iv) any message or other communication received or transaction entered into through or from the Service, (v) unauthorised access to or alteration of the Customer’s or any End User’s transmissions or data, (vi) the statements or conduct of any person having access to the Service, (vii) any other matter relating to the Service; regardless of whether the same are suffered directly or indirectly or are immediate or consequential, and whether the same arise in contract, tort or otherwise; provided, however, that this clause shall not prevent claims for direct financial loss suffered by the Customer due to the Supplier’s intentional or grossly negligent breach of this Agreement, and that the total liability of the Supplier, whether in contract, tort or otherwise shall in no circumstances exceed a sum equal to the amount that the Customer has paid to the Supplier during the twelve months immediately preceding that month in which the breach occurred.</li>
+
+ <li>Any claim that the Customer may have under the Agreement or in connection herewith must be filed with the appropriate forum within one year after such claim arose, or shall be forever barred.</li>
+ </ol>
+
+ <h3>L. Force majeure</h3>
+ <hr/>
+ <ol>
+ <li>No Party shall be liable to the other for breaching its obligations due to a circumstance beyond its control, such as, for example, an act of God, act of government, war, civil unrest, act of terror, strike, internet service provider failure or any other circumstance qualifying as force majeure. However, nothing in this clause shall excuse a Party from any payment obligation hereunder.</li>
+ </ol>
+
+ <h3>M. Indemnification</h3>
+ <hr/>
+ <ol>
+ <li>The Customer will defend, or at its option settle (with no harm or cost to the Supplier), any third party lawsuit or other proceeding brought against the Supplier and/or the Company based upon or otherwise arising out of the Customer’s or any End User’s (i) use of the Service, (ii) content, (iii) misuse of personal data, or (iv) infringement of Intellectual Property.</li>
+ </ol>
+
+ <h3>N. Data protection</h3>
+ <hr/>
+ <ol>
+ <li>The Customer acknowledges that the Supplier may collect information about the Customer and the End Users (i) upon the Customer’s entry into the Agreement or change of the Service (the information entered on the Sign-up Form); (ii) when they visit the Supplier’s website (session information, browsing history at the Supplier’s website, IP address, certain software and hardware attributes) or fill in forms via the Service (the information thus provided); (iii) when they access or use the Service (the location, manner, means and duration of such use or access); and (iv) when otherwise knowingly made available to the Supplier (the information the data subjects make available). When visiting the Supplier’s website, “cookies” may be stored within the visitor’s device.</li>
+
+ <li>The Customer agrees, and warrants to the Supplier that the End Users agree, (i) to the processing of their personal data (as defined under the relevant data protection laws) by the Supplier for the purpose of performing its obligations under the Agreement and, if necessary, enforcing its rights hereunder; (ii) that their personal data may be processed in the country of their domicile as well as outside it; (iii) that the Supplier will not disclose their personal data to any third party unless otherwise required by law or in order to enforce the Agreement.</li>
+
+ <li>The Supplier warrants to the Customer that commercially reasonable measures will be taken to ensure that personal data is processed securely.</li>
+
+ <li>The Supplier has no obligation to monitor or access customer accounts, but may do so in cases where such action is reasonably justified (e.g., in order to prevent illegal or harmful activity or to provide customer support).</li>
+
+ <li>If the Customer chooses to opt in to the Supplier’s mailing programme, the Supplier may use their personal data to send them information about products, services, promotions and events which the Supplier thinks may be of interest to them. Any subscription to such mailing programme may be cancelled at will.</li>
+ </ol>
+
+ <h3>O. Modification and suspension</h3>
+ <hr/>
+ <ol>
+ <li>The Supplier may modify the Service or any part of the Agreement at any time in its sole discretion. If the Supplier makes material changes to the Agreement, the Supplier will notify the Customer by email or by posting a notice on the website site before the changes are effective. Any new features that augment or enhance the current Service, including the release of new tools and resources, shall be subject to the Terms of Service. Continued use of the Service after any such changes shall constitute the Customer's consent to such changes. The most current version of the Terms of Service can be accessed at any time at <a href="http://docs.servoapp.com/terms/">http://docs.servoapp.com/terms/</a></li>
+
+ <li>The Supplier may discontinue all or any part of the Service upon a 30 days’ prior notice.</li>
+
+ <li>The Supplier may suspend performance under the Agreement in whole or in part with immediate effect if it is required by a court order, magisterial decision or competent regulatory body to temporarily or permanently refrain from continuing to perform its obligations hereunder.</li>
+ </ol>
+
+ <h3>P. Termination</h3>
+ <hr/>
+ <ol>
+ <li>Either Party may cancel the Agreement at any time with a 30 days’ prior notice to the other Party.</li>
+
+ <li>If the Agreement is cancelled due to the other Party’s material breach, no warning or advance notice shall be required for the cancellation to be effective (i.e., the Agreement may be cancelled forthwith).</li>
+
+ <li>A material breach of the Agreement shall (inter alia) be deemed to have occurred if: (i) a Party is in breach of any of its obligations hereunder and fails to discontinue or remedy such breach within two weeks after notice from the other Party specifying the breach and requiring it to be discontinued or remedied; (ii) a Party is in persistent breach of any of its obligations hereunder and the respective breach cannot be remedied; (iii) a breach by one Party deprives the other of the whole benefit, or substantially all of the benefit, which the latter was entitled to hereunder.</li>
+
+ <li>Any cancellation of the Agreement shall be without prejudice to the Parties’ rights and remedies that have accrued prior to the cancellation.</li>
+
+ <li>The Customer understands and agrees that upon any termination of the Agreement (i) all rights that the Customer has been granted hereunder will terminate; (ii) the Customer shall cease all activities authorised by the Agreement; (iii) they shall immediately disburse to the Supplier all sums that are due to the Supplier hereunder; (iv) they will receive no refund or exchange for any unused time on a subscription, for any license or subscription fee, any content or data associated with their account, or for anything else.</li>
+ </ol>
+
+ <h3>R. Governing law and dispute resolution</h3>
+ <hr/>
+ <ol>
+ <li>The laws of England shall govern this Agreement and all matters relating hereto.</li>
+
+ <li>Any controversy or claim arising out of or relating to this Agreement, or the breach thereof, shall be settled by arbitration administered by London Court of International Arbitration in accordance with its Arbitration Rules and judgment on the award rendered by the arbitrator(s) may be entered in any court having jurisdiction thereof. The venue of the arbitration shall be London, England.</li>
+
+ <li>The arbitration proceedings shall be conducted before a single arbitrator, unless the amount in dispute exceeds EUR€ 200,000 (two hundred thousand), in which case the dispute shall be heard and determined by three arbitrators.</li>
+
+ <li>The arbitrator(s) shall award to the prevailing party, if any, as determined by the arbitrator(s), all reasonable arbitration costs of that party, i.e. all reasonable pre-award expenses of the arbitration, including the arbitrator’s/s’ and administrative fees and necessary out-of-pocket expenses such as costs of translation and interpretation, notarisation and certification, legalisation and apostillisation, state and court fees and reasonable experts’ and attorneys’ fees. Costs relating to office, copying, use of databases, internet, telephone and other means of communication and correspondence (whether incurred by a party, its attorney, expert or a witness) shall not be awarded.</li>
+ </ol>
+
+ <h3>S. Miscellaneous</h3>
+ <hr/>
+ <ol>
+ <li>The Customer hereby consents to the Supplier’s inclusion of the Customer’s name in a customer listing, provided that the Customer is not the sole customer listed. The issuance of any press release shall be subject to the prior consent of both Parties.</li>
+
+ <li>Any amount hereunder not paid when due shall be subject to default interest at the rate of twenty per cent (20%) per annum until payment is received.</li>
+
+ <li>All conversion and remittance charges relating to any payment hereunder shall be borne by the payer (not the beneficiary).</li>
+
+ <li>Having sufficiently considered each term of the Agreement both individually and in conjunction with other terms, each Party hereby confirms to the other that they find the Agreement fair and not oppressive or harmful in any respect.</li>
+
+ <li>Questions about the Terms of Service should be sent to <a href="mailto:support@servoapp.com">support@servoapp.com</a>.</li>
+ </ol>
+</div>
+
+{% endblock content %} \ No newline at end of file
diff --git a/apps/docs/templatetags/__init__.py b/apps/docs/templatetags/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/docs/templatetags/__init__.py
diff --git a/apps/docs/templatetags/motor_tags.py b/apps/docs/templatetags/motor_tags.py
new file mode 100644
index 0000000..672f2a1
--- /dev/null
+++ b/apps/docs/templatetags/motor_tags.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from django import template
+register = template.Library()
+
+from django.utils import safestring
+
+
+@register.filter
+def markdown(text):
+ import markdown
+ result = markdown.markdown(text)
+ return safestring.mark_safe(result)
diff --git a/apps/docs/tests.py b/apps/docs/tests.py
new file mode 100644
index 0000000..501deb7
--- /dev/null
+++ b/apps/docs/tests.py
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.assertEqual(1 + 1, 2)
diff --git a/apps/docs/views.py b/apps/docs/views.py
new file mode 100644
index 0000000..924360d
--- /dev/null
+++ b/apps/docs/views.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from django.shortcuts import render, redirect
+
+from docs.models import Article
+
+
+def index(request):
+ data = {'topics': Article.objects.filter(published=True)}
+ data['title'] = u'ServoApp Help'
+ return render(request, "docs_index.html", data)
+
+
+def view_article(request, slug):
+ article = Article.objects.get(slug=slug)
+ data = {'article': article}
+ data['topics'] = Article.objects.filter(published=True)
+ data['title'] = article.title
+ return render(request, 'docs_view.html', data)
diff --git a/apps/troubleshooting/__init__.py b/apps/troubleshooting/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/apps/troubleshooting/__init__.py
diff --git a/apps/troubleshooting/models.py b/apps/troubleshooting/models.py
new file mode 100644
index 0000000..cd1edf3
--- /dev/null
+++ b/apps/troubleshooting/models.py
@@ -0,0 +1,19 @@
+from django.db import models
+from apps.core.models import ServiceProvider
+from apps.checkin.models import ServiceOrder
+
+
+class Question(models.Model):
+ sp = models.ForeignKey(ServiceProvider)
+ required = models.BooleanField(default=True)
+ question = models.CharField(max_length=256)
+
+
+class Choice(models.Model):
+ question = models.ForeignKey(Question)
+ choice = models.CharField(max_length=256)
+
+
+class Answer(models.Model):
+ choice = models.ForeignKey(Choice)
+ so = models.ForeignKey(ServiceOrder)
diff --git a/apps/troubleshooting/tests.py b/apps/troubleshooting/tests.py
new file mode 100644
index 0000000..501deb7
--- /dev/null
+++ b/apps/troubleshooting/tests.py
@@ -0,0 +1,16 @@
+"""
+This file demonstrates writing tests using the unittest module. These will pass
+when you run "manage.py test".
+
+Replace this with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+
+class SimpleTest(TestCase):
+ def test_basic_addition(self):
+ """
+ Tests that 1 + 1 always equals 2.
+ """
+ self.assertEqual(1 + 1, 2)
diff --git a/apps/troubleshooting/views.py b/apps/troubleshooting/views.py
new file mode 100644
index 0000000..60f00ef
--- /dev/null
+++ b/apps/troubleshooting/views.py
@@ -0,0 +1 @@
+# Create your views here.