Browse Source

- Statusmeldungen und Kommentare getrennt.
- Nachverfolgung von Fehlern
- Statistiken

Robert Bedner 10 years ago
parent
commit
4f0b2b68be

+ 1 - 0
.idea/Fehlerbericht.iml

@@ -28,6 +28,7 @@
     </orderEntry>
     <orderEntry type="library" name="Node.js Dependencies for Fehlerbericht" level="project" />
     <orderEntry type="library" name="Node.js Dependencies for Fehlerbericht" level="project" />
+    <orderEntry type="library" name="Node.js v0.10.21 Core Modules" level="application" />
   </component>
 </module>
 

+ 1 - 1
.idea/inspectionProfiles/Project_Default.xml

@@ -2,6 +2,6 @@
   <profile version="1.0" is_locked="false">
     <option name="myName" value="Project Default" />
     <option name="myLocal" value="false" />
-    <inspection_tool class="JSLint" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="JSHint" enabled="true" level="ERROR" enabled_by_default="true" />
   </profile>
 </component>

+ 2 - 1
.idea/jsLibraryMappings.xml

@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="JavaScriptLibraryMappings">
-    <file url="file://$PROJECT_DIR$" libraries="{Node.js Dependencies for Fehlerbericht, Node.js Dependencies for Kasse}" />
+    <file url="file://$PROJECT_DIR$" libraries="{Node.js Dependencies for Kasse}" />
+    <file url="PROJECT" libraries="{Node.js v0.10.21 Core Modules}" />
   </component>
 </project>
 

+ 69 - 0
.idea/jsLinters/jshint.xml

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JSHintConfiguration" version="2.3.0" use-config-file="false">
+    <option bitwise="true" />
+    <option camelcase="false" />
+    <option curly="true" />
+    <option eqeqeq="true" />
+    <option es3="false" />
+    <option forin="true" />
+    <option freeze="false" />
+    <option immed="false" />
+    <option newcap="false" />
+    <option noarg="true" />
+    <option noempty="true" />
+    <option nonew="true" />
+    <option plusplus="false" />
+    <option undef="true" />
+    <option strict="true" />
+    <option trailing="false" />
+    <option latedef="false" />
+    <option unused="false" />
+    <option quotmark="false" />
+    <option asi="false" />
+    <option boss="false" />
+    <option debug="false" />
+    <option eqnull="false" />
+    <option esnext="false" />
+    <option evil="false" />
+    <option expr="false" />
+    <option funcscope="false" />
+    <option globalstrict="false" />
+    <option iterator="false" />
+    <option lastsemic="false" />
+    <option laxbreak="false" />
+    <option laxcomma="false" />
+    <option loopfunc="false" />
+    <option moz="false" />
+    <option multistr="false" />
+    <option notypeof="false" />
+    <option proto="false" />
+    <option scripturl="false" />
+    <option smarttabs="false" />
+    <option shadow="false" />
+    <option sub="false" />
+    <option supernew="false" />
+    <option validthis="false" />
+    <option browser="true" />
+    <option couch="false" />
+    <option devel="false" />
+    <option dojo="false" />
+    <option jquery="true" />
+    <option mootools="false" />
+    <option node="false" />
+    <option nonstandard="false" />
+    <option phantom="false" />
+    <option prototypejs="false" />
+    <option rhino="false" />
+    <option worker="false" />
+    <option wsh="false" />
+    <option yui="false" />
+    <option nomen="false" />
+    <option onevar="false" />
+    <option passfail="false" />
+    <option white="false" />
+    <option maxerr="50" />
+    <option predef="_, angular, $, moment" />
+  </component>
+</project>
+

+ 0 - 33
.idea/misc.xml

@@ -1,38 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectInspectionProfilesVisibleTreeState">
-    <entry key="Project Default">
-      <profile-state>
-        <expanded-state>
-          <State>
-            <id />
-          </State>
-        </expanded-state>
-        <selected-state>
-          <State>
-            <id>CoffeeScript</id>
-          </State>
-        </selected-state>
-      </profile-state>
-    </entry>
-  </component>
   <component name="ProjectRootManager" version="2" />
-  <component name="SvnConfiguration" maxAnnotateRevisions="500" myUseAcceleration="nothing" myAutoUpdateAfterCommit="false" cleanupOnStartRun="false" SSL_PROTOCOLS="all">
-    <option name="USER" value="" />
-    <option name="PASSWORD" value="" />
-    <option name="mySSHConnectionTimeout" value="30000" />
-    <option name="mySSHReadTimeout" value="30000" />
-    <option name="LAST_MERGED_REVISION" />
-    <option name="MERGE_DRY_RUN" value="false" />
-    <option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
-    <option name="UPDATE_LOCK_ON_DEMAND" value="false" />
-    <option name="IGNORE_SPACES_IN_MERGE" value="false" />
-    <option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
-    <option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
-    <option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
-    <option name="FORCE_UPDATE" value="false" />
-    <option name="IGNORE_EXTERNALS" value="false" />
-    <myIsUseDefaultProxy>false</myIsUseDefaultProxy>
-  </component>
 </project>
 

+ 274 - 259
.idea/workspace.xml

@@ -23,105 +23,65 @@
   </component>
   <component name="FileEditorManager">
     <leaf>
-      <file leaf-file-name="index.html" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/index.html">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="95" column="56" selection-start="3497" selection-end="3497" vertical-scroll-proportion="0.0" vertical-offset="1456" max-vertical-offset="2057">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="app.js" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="29" column="0" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="595">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="overview.html" pinned="false" current="true" current-in-tab="true">
-        <entry file="file://$PROJECT_DIR$/app/views/overview.html">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="174" column="106" selection-start="8094" selection-end="8094" vertical-scroll-proportion="0.69863015" vertical-offset="2550" max-vertical-offset="4590">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
       <file leaf-file-name="overview.js" pinned="false" current="false" current-in-tab="false">
         <entry file="file://$PROJECT_DIR$/app/scripts/controllers/overview.js">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="90" column="10" selection-start="2553" selection-end="2553" vertical-scroll-proportion="0.0" vertical-offset="1071" max-vertical-offset="2040">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="main.html" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/views/main.html">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="-7.8461537" vertical-offset="0" max-vertical-offset="1173">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="package.json" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/package.json">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="29" column="41" selection-start="948" selection-end="948" vertical-scroll-proportion="0.0" vertical-offset="51" max-vertical-offset="782">
+            <state line="278" column="31" selection-start="9056" selection-end="9056" vertical-scroll-proportion="0.0" vertical-offset="4277" max-vertical-offset="6732">
               <folding />
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="bower.json" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/bower.json">
-          <provider selected="true" editor-type-id="text-editor">
-            <state line="23" column="1" selection-start="646" selection-end="646" vertical-scroll-proportion="0.0" vertical-offset="391" max-vertical-offset="493">
-              <folding />
-            </state>
-          </provider>
-        </entry>
-      </file>
-      <file leaf-file-name="bower.json" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/bower_components/bootstrap/bower.json">
+      <file leaf-file-name="db.php" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/db.php">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="22" column="50" selection-start="642" selection-end="642" vertical-scroll-proportion="-8.076923" vertical-offset="164" max-vertical-offset="748">
-              <folding />
+            <state line="124" column="76" selection-start="5369" selection-end="5369" vertical-scroll-proportion="-21.346153" vertical-offset="1553" max-vertical-offset="2618">
+              <folding>
+                <marker date="1427374808019" expanded="true" signature="653:889" placeholder="SELECT sm.*,..status_meldung..." />
+                <marker date="1427374808019" expanded="true" signature="1191:1326" placeholder="UPDATE kunde..." />
+                <marker date="1427374808019" expanded="true" signature="1590:1957" placeholder="UPDATE kunde..." />
+                <marker date="1427374808019" expanded="true" signature="1997:2017" placeholder="SELECT * FRO..kunden..." />
+                <marker date="1427374808019" expanded="true" signature="2111:2149" placeholder="SELECT kunde..kunden_config..." />
+                <marker date="1427374808019" expanded="true" signature="2460:2559" placeholder="SELECT * FRO..kunden_config..." />
+                <marker date="1427374808019" expanded="true" signature="2597:2689" placeholder="SELECT * FRO..kunden_config..." />
+                <marker date="1427374808019" expanded="true" signature="2882:2904" placeholder="SELECT * FRO..benutzer..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3264" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3263" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3251" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3458:3603" placeholder="UPDATE statu..." />
+                <marker date="1427374808019" expanded="true" signature="3642:3857" placeholder="UPDATE statu..." />
+                <marker date="1427374808019" expanded="true" signature="3642:3862" placeholder="UPDATE statu..." />
+                <marker date="1427374808019" expanded="true" signature="3648:3862" placeholder="INSERT INTO ..." />
+                <marker date="1427374808019" expanded="true" signature="3896:4022" placeholder="SELECT * FRO..status_kommentar..." />
+                <marker date="1427374808019" expanded="true" signature="4428:5429" placeholder="SELECT a.dat..arbeitstage..." />
+              </folding>
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="import.php" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/import.php">
+      <file leaf-file-name="overview.html" pinned="false" current="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/app/views/overview.html">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="91" column="40" selection-start="2968" selection-end="2968" vertical-scroll-proportion="-14.615385" vertical-offset="1167" max-vertical-offset="1751">
+            <state line="122" column="152" selection-start="6657" selection-end="6657" vertical-scroll-proportion="-16.076923" vertical-offset="1656" max-vertical-offset="7157">
               <folding>
-                <marker date="1411657879733" expanded="true" signature="392:416" placeholder="SELECT kunde..kunden..." />
-                <marker date="1411657879733" expanded="true" signature="2806:2930" placeholder="INSERT INTO ..." />
-                <marker date="1411657879733" expanded="true" signature="2806:2887" placeholder="INSERT INTO ..." />
-                <marker date="1411657879733" expanded="true" signature="2806:2886" placeholder="INSERT INTO ..." />
-                <marker date="1411657879733" expanded="true" signature="2806:2884" placeholder="INSERT INTO ..." />
+                <element signature="n#style#0;n#th#0;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+                <element signature="n#style#0;n#th#1;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+                <element signature="n#style#0;n#th#2;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+                <element signature="n#style#0;n#th#3;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+                <element signature="n#style#0;n#th#4;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
               </folding>
             </state>
           </provider>
         </entry>
       </file>
-      <file leaf-file-name="db.php" pinned="false" current="false" current-in-tab="false">
-        <entry file="file://$PROJECT_DIR$/app/db.php">
+      <file leaf-file-name="bower.json" pinned="false" current="true" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/bower.json">
           <provider selected="true" editor-type-id="text-editor">
-            <state line="16" column="194" selection-start="900" selection-end="900" vertical-scroll-proportion="-6.5384617" vertical-offset="102" max-vertical-offset="765">
-              <folding>
-                <marker date="1412006026713" expanded="true" signature="207:261" placeholder="SELECT * FRO..statusmail..." />
-                <marker date="1412006026713" expanded="true" signature="207:292" placeholder="SELECT * FRO..statusmail..." />
-                <marker date="1412006026713" expanded="true" signature="207:303" placeholder="SELECT * FRO..statusmail..." />
-                <marker date="1412006026713" expanded="true" signature="610:630" placeholder="SELECT * FRO..kunden..." />
-                <marker date="1412006026713" expanded="true" signature="728:1568" placeholder="SELECT *, ti..arbeitstage..." />
-                <marker date="1412006026713" expanded="true" signature="728:1249" placeholder="SELECT a.dat..." />
-              </folding>
+            <state line="17" column="27" selection-start="541" selection-end="541" vertical-scroll-proportion="0.38076416" vertical-offset="0" max-vertical-offset="759">
+              <folding />
             </state>
           </provider>
         </entry>
@@ -137,13 +97,27 @@
     <option name="changedFiles">
       <list>
         <option value="$PROJECT_DIR$/app/views/main.html" />
-        <option value="$PROJECT_DIR$/app/index.html" />
-        <option value="$PROJECT_DIR$/app/scripts/controllers/main.js" />
         <option value="$PROJECT_DIR$/package.json" />
+        <option value="$PROJECT_DIR$/app/bower_components/bootstrap/bower.json" />
+        <option value="$PROJECT_DIR$/app/scripts/controllers/main.js" />
+        <option value="$PROJECT_DIR$/app/views/calendar.html" />
+        <option value="$PROJECT_DIR$/bower.json" />
+        <option value="$USER_HOME$/Desktop/GAPS.xml.json" />
+        <option value="$USER_HOME$/Desktop/GAPS_Vers_taegl.xml.json" />
+        <option value="$USER_HOME$/Desktop/Tasks_Test/config/info/info.json" />
+        <option value="D:/Downloads/fehlerbericht.json" />
+        <option value="D:/Downloads/info.json" />
+        <option value="$PROJECT_DIR$/app/scripts/controllers/calendar.js" />
+        <option value="$USER_HOME$/Desktop/Tasks_Test/config/GAPS_Vers.xml" />
+        <option value="$PROJECT_DIR$/app/views/config.html" />
+        <option value="$PROJECT_DIR$/app/views/customers.html" />
+        <option value="$PROJECT_DIR$/app/scripts/controllers/config.js" />
+        <option value="$PROJECT_DIR$/app/scripts/controllers/customers.js" />
         <option value="$PROJECT_DIR$/app/scripts/app.js" />
+        <option value="$PROJECT_DIR$/app/scripts/controllers/stats.js" />
+        <option value="$PROJECT_DIR$/app/index.html" />
+        <option value="$PROJECT_DIR$/app/views/stats.html" />
         <option value="$PROJECT_DIR$/app/import.php" />
-        <option value="$PROJECT_DIR$/bower.json" />
-        <option value="$PROJECT_DIR$/app/bower_components/bootstrap/bower.json" />
         <option value="$PROJECT_DIR$/app/db.php" />
         <option value="$PROJECT_DIR$/app/scripts/controllers/overview.js" />
         <option value="$PROJECT_DIR$/app/views/overview.html" />
@@ -164,10 +138,26 @@
     </include_path>
   </component>
   <component name="ProjectFrameBounds">
-    <option name="x" value="-8" />
-    <option name="y" value="-8" />
+    <option name="x" value="1912" />
+    <option name="y" value="316" />
     <option name="width" value="1936" />
-    <option name="height" value="1056" />
+    <option name="height" value="1216" />
+  </component>
+  <component name="ProjectInspectionProfilesVisibleTreeState">
+    <entry key="Project Default">
+      <profile-state>
+        <expanded-state>
+          <State>
+            <id />
+          </State>
+        </expanded-state>
+        <selected-state>
+          <State>
+            <id>CoffeeScript</id>
+          </State>
+        </selected-state>
+      </profile-state>
+    </entry>
   </component>
   <component name="ProjectLevelVcsManager" settingsEditedManually="false">
     <OptionsSetting value="true" id="Add" />
@@ -195,7 +185,6 @@
       <sortByType />
     </navigator>
     <panes>
-      <pane id="Scope" />
       <pane id="ProjectPane">
         <subPane>
           <PATH>
@@ -286,53 +275,14 @@
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
           </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="Fehlerbericht" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="Fehlerbericht" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="app" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="bower_components" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="Fehlerbericht" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="Fehlerbericht" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="app" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="bower_components" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="bootstrap" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
         </subPane>
       </pane>
+      <pane id="Scope" />
     </panes>
   </component>
   <component name="PropertiesComponent">
     <property name="options.splitter.main.proportions" value="0.3" />
-    <property name="options.lastSelected" value="preferences.externalResources" />
+    <property name="options.lastSelected" value="Settings.JavaScript.Linters.JSHint" />
     <property name="last_opened_file_path" value="D:/dev/msysgit/cmd/git.exe" />
     <property name="options.splitter.details.proportions" value="0.2" />
     <property name="options.searchVisible" value="true" />
@@ -344,8 +294,23 @@
     <property name="dynamic.classpath" value="false" />
     <property name="SearchEverywhereHistory" value="$" />
     <property name="LayoutCode.rearrangeEntriesJSON" value="false" />
+    <property name="recentsLimit" value="5" />
+    <property name="LayoutCode.rearrangeEntriesPlain text" value="false" />
+    <property name="LayoutCode.rearrangeEntriesXML" value="false" />
+  </component>
+  <component name="RecentsManager">
+    <key name="CopyFile.RECENT_KEYS">
+      <recent name="D:\Projekte\GlobalCube\Fehlerbericht\app\views" />
+      <recent name="D:\Projekte\GlobalCube\Fehlerbericht\app\scripts\controllers" />
+    </key>
   </component>
-  <component name="RunManager">
+  <component name="RunManager" selected="PHPUnit.Fehlerbericht">
+    <configuration default="false" name="Fehlerbericht" type="PHPUnitRunConfigurationType" factoryName="PHPUnit" temporary="true">
+      <TestRunner directory="$PROJECT_DIR$" />
+      <RunnerSettings RunnerId="PhpRunner" />
+      <ConfigurationWrapper RunnerId="PhpRunner" />
+      <method />
+    </configuration>
     <configuration default="true" type="PHPUnitRunConfigurationType" factoryName="PHPUnit">
       <TestRunner />
       <method />
@@ -373,9 +338,33 @@
       <option name="CONTEXT_PROVIDER" />
       <method />
     </configuration>
-    <list size="0" />
+    <list size="1">
+      <item index="0" class="java.lang.String" itemvalue="PHPUnit.Fehlerbericht" />
+    </list>
+    <recent_temporary>
+      <list size="1">
+        <item index="0" class="java.lang.String" itemvalue="PHPUnit.Fehlerbericht" />
+      </list>
+    </recent_temporary>
   </component>
   <component name="ShelveChangesManager" show_recycled="false" />
+  <component name="SvnConfiguration" maxAnnotateRevisions="500" myUseAcceleration="nothing" myAutoUpdateAfterCommit="false" cleanupOnStartRun="false" SSL_PROTOCOLS="all">
+    <option name="USER" value="" />
+    <option name="PASSWORD" value="" />
+    <option name="mySSHConnectionTimeout" value="30000" />
+    <option name="mySSHReadTimeout" value="30000" />
+    <option name="LAST_MERGED_REVISION" />
+    <option name="MERGE_DRY_RUN" value="false" />
+    <option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
+    <option name="UPDATE_LOCK_ON_DEMAND" value="false" />
+    <option name="IGNORE_SPACES_IN_MERGE" value="false" />
+    <option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
+    <option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
+    <option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
+    <option name="FORCE_UPDATE" value="false" />
+    <option name="IGNORE_EXTERNALS" value="false" />
+    <myIsUseDefaultProxy>false</myIsUseDefaultProxy>
+  </component>
   <component name="TaskManager">
     <task active="true" id="Default" summary="Default task">
       <changelist id="e6a1298f-f559-449e-a74b-e7d36fe3b7cd" name="Default" comment="" />
@@ -385,27 +374,28 @@
     <servers />
   </component>
   <component name="ToolWindowManager">
-    <frame x="-8" y="-8" width="1936" height="1056" extended-state="0" />
+    <frame x="1912" y="316" width="1936" height="1216" extended-state="6" />
     <editor active="true" />
     <layout>
       <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
-      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
+      <window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.26805055" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.13541667" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.13697916" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
-      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32911393" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
-      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.26805055" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32911393" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32911393" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
+      <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
       <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
+      <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
+      <window_info id="Command Line Tools Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32911393" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
     </layout>
   </component>
   <component name="Vcs.Log.UiProperties">
@@ -425,86 +415,22 @@
     <breakpoint-manager />
   </component>
   <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/app/index.html">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="98" column="56" selection-start="3711" selection-end="3711" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="2091">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="29" column="0" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0" vertical-offset="493" max-vertical-offset="595">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/app/views/overview.html">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="62" column="64" selection-start="2735" selection-end="2735" vertical-scroll-proportion="0.0" vertical-offset="612" max-vertical-offset="1564">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/overview.js">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="69" column="7" selection-start="2069" selection-end="2069" vertical-scroll-proportion="0.0" vertical-offset="1173" max-vertical-offset="1275">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/package.json">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="29" column="41" selection-start="948" selection-end="948" vertical-scroll-proportion="0.0" vertical-offset="51" max-vertical-offset="782">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/bower.json">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="23" column="1" selection-start="646" selection-end="646" vertical-scroll-proportion="0.0" vertical-offset="391" max-vertical-offset="493">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/app/bower_components/bootstrap/bower.json">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="22" column="50" selection-start="642" selection-end="642" vertical-scroll-proportion="0.0" vertical-offset="164" max-vertical-offset="748">
-          <folding />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/app/import.php">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="26" column="42" selection-start="873" selection-end="873" vertical-scroll-proportion="0.0" vertical-offset="153" max-vertical-offset="1751">
-          <folding>
-            <marker date="1411657879733" expanded="true" signature="392:416" placeholder="SELECT kunde..kunden..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2930" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2887" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2886" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2884" placeholder="INSERT INTO ..." />
-          </folding>
-        </state>
+        <state line="26" column="42" selection-start="873" selection-end="873" vertical-scroll-proportion="0.0" vertical-offset="153" max-vertical-offset="1751" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/db.php">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="10" column="151" selection-start="388" selection-end="388" vertical-scroll-proportion="0.0" vertical-offset="79" max-vertical-offset="663">
-          <folding>
-            <marker date="1412006026713" expanded="true" signature="207:261" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="207:292" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="207:303" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="610:630" placeholder="SELECT * FRO..kunden..." />
-            <marker date="1412006026713" expanded="true" signature="728:1568" placeholder="SELECT *, ti..arbeitstage..." />
-            <marker date="1412006026713" expanded="true" signature="728:1249" placeholder="SELECT a.dat..." />
-          </folding>
-        </state>
+        <state line="10" column="151" selection-start="388" selection-end="388" vertical-scroll-proportion="0.0" vertical-offset="79" max-vertical-offset="663" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/index.html">
       <provider selected="true" editor-type-id="text-editor">
         <state line="64" column="41" selection-start="2338" selection-end="2338" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="2040">
-          <folding />
+          <folding>
+            <marker date="1426582695479" expanded="true" signature="-1:-1" placeholder="..." />
+          </folding>
         </state>
       </provider>
     </entry>
@@ -524,9 +450,7 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/views/main.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173">
-          <folding />
-        </state>
+        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/controllers/main.js">
@@ -536,15 +460,15 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663">
-          <folding />
-        </state>
+        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/index.html">
       <provider selected="true" editor-type-id="text-editor">
         <state line="64" column="41" selection-start="2336" selection-end="2336" vertical-scroll-proportion="0.0" vertical-offset="923" max-vertical-offset="2023">
-          <folding />
+          <folding>
+            <marker date="1426582695479" expanded="true" signature="-1:-1" placeholder="..." />
+          </folding>
         </state>
       </provider>
     </entry>
@@ -564,9 +488,7 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/views/main.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173">
-          <folding />
-        </state>
+        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/controllers/main.js">
@@ -576,15 +498,15 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663">
-          <folding />
-        </state>
+        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/index.html">
       <provider selected="true" editor-type-id="text-editor">
         <state line="64" column="41" selection-start="2336" selection-end="2336" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="2023">
-          <folding />
+          <folding>
+            <marker date="1426582695479" expanded="true" signature="-1:-1" placeholder="..." />
+          </folding>
         </state>
       </provider>
     </entry>
@@ -604,9 +526,7 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/views/main.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173">
-          <folding />
-        </state>
+        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="0.0" vertical-offset="204" max-vertical-offset="1173" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/controllers/main.js">
@@ -616,21 +536,12 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663">
-          <folding />
-        </state>
+        <state line="31" column="15" selection-start="697" selection-end="697" vertical-scroll-proportion="0.0" vertical-offset="527" max-vertical-offset="663" />
       </provider>
     </entry>
     <entry file="jar://$APPLICATION_HOME_DIR$/lib/phpstorm.jar!/resources/html5-schema/block.rnc">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="198" column="22" selection-start="4044" selection-end="4044" vertical-scroll-proportion="0.46529284" vertical-offset="2937" max-vertical-offset="3859">
-          <folding />
-        </state>
-      </provider>
-    </entry>
-    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/main.js">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="18" column="34" selection-start="403" selection-end="403" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1870" />
+        <state line="198" column="22" selection-start="4044" selection-end="4044" vertical-scroll-proportion="0.46529284" vertical-offset="2937" max-vertical-offset="3859" />
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/.travis.yml">
@@ -660,83 +571,187 @@
     </entry>
     <entry file="file://$PROJECT_DIR$/package.json">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="29" column="41" selection-start="948" selection-end="948" vertical-scroll-proportion="0.0" vertical-offset="51" max-vertical-offset="782">
+        <state line="29" column="41" selection-start="948" selection-end="948" vertical-scroll-proportion="0.0" vertical-offset="51" max-vertical-offset="782" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/bower_components/bootstrap/bower.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="22" column="50" selection-start="642" selection-end="642" vertical-scroll-proportion="0.0" vertical-offset="164" max-vertical-offset="748" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/main.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="-7.8461537" vertical-offset="0" max-vertical-offset="1173" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/calendar.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="0" column="20" selection-start="20" selection-end="20" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="584" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/bower_components/fullcalendar/bower.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="2" column="19" selection-start="42" selection-end="47" vertical-scroll-proportion="-1.3076923" vertical-offset="0" max-vertical-offset="731" />
+      </provider>
+    </entry>
+    <entry file="file://$USER_HOME$/Desktop/Tasks_Test/config/info/info.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="955" column="6" selection-start="25909" selection-end="25909" vertical-scroll-proportion="0.02910959" vertical-offset="16218" max-vertical-offset="27574" />
+      </provider>
+    </entry>
+    <entry file="file://D:/Downloads/fehlerbericht.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="1709" column="20" selection-start="77156" selection-end="77156" vertical-scroll-proportion="-0.65384614" vertical-offset="29036" max-vertical-offset="29648" />
+      </provider>
+    </entry>
+    <entry file="file://D:/Downloads/info.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="28050" column="6" selection-start="819398" selection-end="819398" vertical-scroll-proportion="-6.1153846" vertical-offset="476691" max-vertical-offset="477275" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/calendar.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="18" column="49" selection-start="611" selection-end="611" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1360" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/main.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="11" column="0" selection-start="244" selection-end="244" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="357" />
+      </provider>
+    </entry>
+    <entry file="file://$USER_HOME$/Desktop/Tasks_Test/config/GAPS_Vers.xml">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="108" column="21" selection-start="4458" selection-end="4458" vertical-scroll-proportion="2.9470305" vertical-offset="0" max-vertical-offset="2023" />
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/config.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="12" column="17" selection-start="350" selection-end="350" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1037">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/bower.json">
+    <entry file="file://$PROJECT_DIR$/app/index.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="91" column="45" selection-start="2681" selection-end="2681" vertical-scroll-proportion="0.0" vertical-offset="1122" max-vertical-offset="2822">
+          <folding>
+            <marker date="1426582695479" expanded="true" signature="-1:-1" placeholder="..." />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="23" column="1" selection-start="646" selection-end="646" vertical-scroll-proportion="0.0" vertical-offset="391" max-vertical-offset="493">
+        <state line="42" column="0" selection-start="1421" selection-end="1421" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1003">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/app/index.html">
+    <entry file="file://$PROJECT_DIR$/app/views/config.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="95" column="56" selection-start="3497" selection-end="3497" vertical-scroll-proportion="0.0" vertical-offset="1456" max-vertical-offset="2057">
+        <state line="9" column="142" selection-start="460" selection-end="460" vertical-scroll-proportion="0.0" vertical-offset="153" max-vertical-offset="850">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/app/views/main.html">
+    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/stats.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="12" column="20" selection-start="649" selection-end="657" vertical-scroll-proportion="-7.8461537" vertical-offset="0" max-vertical-offset="1173">
+        <state line="15" column="83" selection-start="562" selection-end="562" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1139">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/app/bower_components/bootstrap/bower.json">
+    <entry file="file://$PROJECT_DIR$/app/views/stats.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="22" column="50" selection-start="642" selection-end="642" vertical-scroll-proportion="-8.076923" vertical-offset="164" max-vertical-offset="748">
+        <state line="18" column="10" selection-start="661" selection-end="661" vertical-scroll-proportion="0.0" vertical-offset="306" max-vertical-offset="425">
           <folding />
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/app/scripts/app.js">
+    <entry file="file://$PROJECT_DIR$/app/import.bat">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="29" column="0" selection-start="595" selection-end="595" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="595">
+        <state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="785">
           <folding />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/import.php">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="91" column="40" selection-start="2968" selection-end="2968" vertical-scroll-proportion="-14.615385" vertical-offset="1167" max-vertical-offset="1751">
+        <state line="19" column="0" selection-start="624" selection-end="624" vertical-scroll-proportion="-12.423077" vertical-offset="0" max-vertical-offset="1972">
           <folding>
-            <marker date="1411657879733" expanded="true" signature="392:416" placeholder="SELECT kunde..kunden..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2930" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2887" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2886" placeholder="INSERT INTO ..." />
-            <marker date="1411657879733" expanded="true" signature="2806:2884" placeholder="INSERT INTO ..." />
+            <marker date="1427288219797" expanded="true" signature="-1:-1" placeholder="SELECT kunde..kunden..." />
+            <marker date="1427288219797" expanded="true" signature="-1:-1" placeholder="INSERT INTO ..." />
+            <marker date="1427288219797" expanded="true" signature="-1:-1" placeholder="SELECT * FRO..kunden_config..." />
+            <marker date="1427288219797" expanded="true" signature="-1:-1" placeholder="INSERT INTO ..." />
           </folding>
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/app/views/customers.html">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="20" column="49" selection-start="833" selection-end="833" vertical-scroll-proportion="-11.115385" vertical-offset="51" max-vertical-offset="4573">
+          <folding />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/app/scripts/controllers/customers.js">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="14" column="23" selection-start="376" selection-end="376" vertical-scroll-proportion="0.0" vertical-offset="68" max-vertical-offset="1632">
+          <folding />
+        </state>
+      </provider>
+    </entry>
     <entry file="file://$PROJECT_DIR$/app/db.php">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="16" column="194" selection-start="900" selection-end="900" vertical-scroll-proportion="-6.5384617" vertical-offset="102" max-vertical-offset="765">
+        <state line="124" column="76" selection-start="5369" selection-end="5369" vertical-scroll-proportion="-21.346153" vertical-offset="1553" max-vertical-offset="2618">
           <folding>
-            <marker date="1412006026713" expanded="true" signature="207:261" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="207:292" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="207:303" placeholder="SELECT * FRO..statusmail..." />
-            <marker date="1412006026713" expanded="true" signature="610:630" placeholder="SELECT * FRO..kunden..." />
-            <marker date="1412006026713" expanded="true" signature="728:1568" placeholder="SELECT *, ti..arbeitstage..." />
-            <marker date="1412006026713" expanded="true" signature="728:1249" placeholder="SELECT a.dat..." />
+            <marker date="1427374808019" expanded="true" signature="653:889" placeholder="SELECT sm.*,..status_meldung..." />
+            <marker date="1427374808019" expanded="true" signature="1191:1326" placeholder="UPDATE kunde..." />
+            <marker date="1427374808019" expanded="true" signature="1590:1957" placeholder="UPDATE kunde..." />
+            <marker date="1427374808019" expanded="true" signature="1997:2017" placeholder="SELECT * FRO..kunden..." />
+            <marker date="1427374808019" expanded="true" signature="2111:2149" placeholder="SELECT kunde..kunden_config..." />
+            <marker date="1427374808019" expanded="true" signature="2460:2559" placeholder="SELECT * FRO..kunden_config..." />
+            <marker date="1427374808019" expanded="true" signature="2597:2689" placeholder="SELECT * FRO..kunden_config..." />
+            <marker date="1427374808019" expanded="true" signature="2882:2904" placeholder="SELECT * FRO..benutzer..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3264" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3263" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3251" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3137:3400" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3458:3603" placeholder="UPDATE statu..." />
+            <marker date="1427374808019" expanded="true" signature="3642:3857" placeholder="UPDATE statu..." />
+            <marker date="1427374808019" expanded="true" signature="3642:3862" placeholder="UPDATE statu..." />
+            <marker date="1427374808019" expanded="true" signature="3648:3862" placeholder="INSERT INTO ..." />
+            <marker date="1427374808019" expanded="true" signature="3896:4022" placeholder="SELECT * FRO..status_kommentar..." />
+            <marker date="1427374808019" expanded="true" signature="4428:5429" placeholder="SELECT a.dat..arbeitstage..." />
           </folding>
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/scripts/controllers/overview.js">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="90" column="10" selection-start="2553" selection-end="2553" vertical-scroll-proportion="0.0" vertical-offset="1071" max-vertical-offset="2040">
+        <state line="278" column="31" selection-start="9056" selection-end="9056" vertical-scroll-proportion="0.0" vertical-offset="4277" max-vertical-offset="6732">
           <folding />
         </state>
       </provider>
     </entry>
     <entry file="file://$PROJECT_DIR$/app/views/overview.html">
       <provider selected="true" editor-type-id="text-editor">
-        <state line="174" column="106" selection-start="8094" selection-end="8094" vertical-scroll-proportion="0.69863015" vertical-offset="2550" max-vertical-offset="4590">
+        <state line="122" column="152" selection-start="6657" selection-end="6657" vertical-scroll-proportion="-16.076923" vertical-offset="1656" max-vertical-offset="7157">
+          <folding>
+            <element signature="n#style#0;n#th#0;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+            <element signature="n#style#0;n#th#1;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+            <element signature="n#style#0;n#th#2;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+            <element signature="n#style#0;n#th#3;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+            <element signature="n#style#0;n#th#4;n#tr#0;n#table#0;n#div#1;n#div#0;n#div#0;n#div#2;n#!!top" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/bower.json">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="17" column="27" selection-start="541" selection-end="541" vertical-scroll-proportion="0.38076416" vertical-offset="0" max-vertical-offset="759">
           <folding />
         </state>
       </provider>

+ 1 - 1
Gruntfile.js

@@ -163,7 +163,7 @@ module.exports = function (grunt) {
     // Automatically inject Bower components into the app
     wiredep: {
       options: {
-        cwd: '<%= yeoman.app %>'
+        cwd: ''
       },
       app: {
         src: ['<%= yeoman.app %>/index.html'],

+ 143 - 34
app/db.php

@@ -1,40 +1,149 @@
 <?php
+header('Access-Control-Allow-Origin: *');
+header('Access-Control-Allow-Methods: GET, POST, PUT');
+header('Access-Control-Allow-Headers: accept, content-type');
+header('Cache-Control: no-cache, must-revalidate');
+header('Content-type: application/json');
+
 $dbh = new PDO("mysql:host=localhost;dbname=tasks", "root", "gc01mysql");
 $dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
 
-if (isset($_GET['kunde']) && isset($_GET['datum'])) {
-	$q = $dbh->query("SELECT * FROM statusmail WHERE kunde = '{$_GET['kunde']}' AND datum = '{$_GET['datum']}' LIMIT 1");
-	$result = $q->fetch(PDO::FETCH_ASSOC);
-	$result['fehlerbericht'] = str_replace("\\", "\\\\", str_replace("\r\"", "\"", str_replace("\r\n", "", $result['fehlerbericht'])));
-	$result['fehlerbericht'] = json_decode($result['fehlerbericht'], true);
-
-} else if (isset($_GET['kunden'])) {
-	$q = $dbh->query("SELECT * FROM kunden");
-	$result = $q->fetchAll(PDO::FETCH_ASSOC);
-} else {
-	$date = date("Y-m");
-
-	$q = $dbh->query("SELECT a.datum, k.kunde, left(k.system, 1) as system, a.bundesland, a.feiertag, k.start_soll, k.ende_soll, s.start, s.ende, s.anzahl, s.bearbeitet, s.benutzer, s.kommentar,
-							if(s.anzahl is null or s.anzahl > 0, 1, 0) as fehler,
-							timediff(k.ende_soll, k.start_soll) as dauer,
-							timediff(s.ende, k.ende_soll) as abweichung,
-							case
-							 when woche = 'Mo-Fr' then mofr
-							 when woche = 'Mo-Sa' then mosa
-							 when woche = 'Mo-So' then moso
-							 when woche = 'Di-So' then diso
-							 else 1
-							end * if(anzahl is null and now() > concat(a.datum, ' ', k.ende_soll), 1, 0) as fehlt
-						FROM arbeitstage a
-						INNER JOIN kunden k USING (bundesland)
-						LEFT JOIN statusmail s USING (datum, kunde)
-						WHERE datum LIKE '{$date}%' AND k.erster_status <= a.datum AND a.datum <= now()
-						AND k.aktiv = 1
-						ORDER BY a.datum, k.ende_soll");
-	$result = $q->fetchAll(PDO::FETCH_ASSOC);
-}
+$data = json_decode(file_get_contents('php://input'), true);
 
-header('Access-Control-Allow-Origin: *');
-header('Cache-Control: no-cache, must-revalidate');
-header('Content-type: application/json');
+switch ($_REQUEST['a']) {
+	case 'fehlerbericht':
+		$kunde = $_REQUEST['kunde'];
+		$datum = $_REQUEST['datum'];
+		$start = $_REQUEST['start'];
+
+		if (count($data) > 0) {
+
+		} else {
+			$q = $dbh->query("SELECT sm.*, ifnull(sk.benutzer, '') as benutzer FROM status_meldung sm
+			 				  LEFT JOIN status_kommentar sk USING (datum, kunde, start)
+							  WHERE sm.datum = '{$datum}' AND sm.kunde = '{$kunde}' AND sm.start = '{$start}' LIMIT 1");
+			$result = $q->fetch(PDO::FETCH_ASSOC);
+			$result['fehlerbericht'] = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $result['fehlerbericht'])));
+			$result['fehlerbericht'] = json_decode($result['fehlerbericht'], true);
+		}
+		break;
+
+	case 'zeit':
+		$q = $dbh->exec("UPDATE kunden SET start_soll = '{$_REQUEST['start_soll']}', ende_soll = '{$_REQUEST['ende_soll']}' WHERE kunde = '{$_REQUEST['kunde']}' ");
+		$error = $dbh->errorInfo();
+		if ($error[0] != '00000') {
+			$result = $error;
+		} else {
+			$result = $_REQUEST;
+		}
+		break;
+
+	case 'kunden':
+		if (count($data) > 0) {
+			foreach ($data as $kunde) {
+				if (isset($kunde['kunde'])) {
+					$q = $dbh->exec("UPDATE kunden SET system = '{$kunde['system']}', start_soll = '{$kunde['start_soll']}', ende_soll = '{$kunde['ende_soll']}',
+									erster_status = '{$kunde['erster_status']}', aktiv = '{$kunde['aktiv']}', woche = '{$kunde['woche']}',
+									bundesland = '{$kunde['bundesland']}', plz = '{$kunde['plz']}', ort = '{$kunde['ort']}' WHERE kunde = '{$kunde['kunde']}' ");
+				}
+			}
+		}
+		$q = $dbh->query("SELECT * FROM kunden");
+		$result = $q->fetchAll(PDO::FETCH_ASSOC);
+		break;
+
+	case 'config':
+		$q = $dbh->query("SELECT kunde, datum FROM kunden_config");
+		$result = array('options' => array());
+		while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
+			$result['options'][$row['kunde']][] = $row['datum'];
+		}
+
+		if (isset($_REQUEST['kunde']) && $_REQUEST['kunde'] != 'undefined') {
+			if (preg_match('/\d{4}-\d{2}-\d{2}/', $_REQUEST['datum'])) {
+				$q = $dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$_REQUEST['kunde']}' AND datum = '{$_REQUEST['datum']}'");
+			} else {
+				$q = $dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$_REQUEST['kunde']}' ORDER BY datum DESC LIMIT 1");
+			}
+			if ($row = $q->fetch(PDO::FETCH_ASSOC)) {
+				$row['info'] = json_decode($row['info'], true);
+				$result['current'] = $row;
+			}
+		}
+		break;
+	case 'benutzer':
+		$q = $dbh->query("SELECT * FROM benutzer");
+		$result = $q->fetchAll(PDO::FETCH_ASSOC);
+		break;
+	case 'kommentar':
+		$id = (isset($_REQUEST['id'])) ? $_REQUEST['id'] : '';
+
+		if (count($data) > 0) {
+			if ($id == '') {
+				$now = date('Y-m-d H:m:i');
+				$q = $dbh->exec("INSERT INTO status_kommentar (kunde, datum, start, benutzer, fehler, status, kommentar, cdate)
+								 VALUES ('{$data['kunde']}','{$data['datum']}','{$data['start']}','{$data['benutzer']}','{$data['fehler']}','{$data['status']}','{$data['kommentar']}','{$now}')");
+				$id = $dbh->lastInsertId();
+
+				$q = $dbh->exec("UPDATE status_meldung SET bearbeitet = '1', kommentar_id = '{$id}'
+							 WHERE kunde = '{$kunde}' AND datum = '{$datum}' AND start = '{$start}' ");
+
+			} else {
+				$q = $dbh->exec("UPDATE status_kommentar SET
+									benutzer = '{$data['benutzer']}',
+									fehler = '{$data['fehler']}',
+									status = '{$data['status']}',
+									kommentar = '{$data['kommentar']}'
+								 WHERE id = '{$id}' ");
+			}
+		}
+		$q = $dbh->query("SELECT * FROM status_kommentar
+						  WHERE datum > date_add(now(), INTERVAL -32 DAY)
+						  ORDER BY datum DESC, mdate DESC");
+		$result = $q->fetchAll(PDO::FETCH_ASSOC);
+		break;
+	default:
+	case 'liste':
+		$datum = (!isset($_REQUEST['datum']) || $_REQUEST['datum'] == '') ? "a.datum > date_add(now(), INTERVAL -32 DAY) AND k.erster_status <= a.datum" : "a.datum = '{$_REQUEST['datum']}' ";
+		$kunde = (!isset($_REQUEST['kunde']) || $_REQUEST['kunde'] == '') ? "1" : "k.kunde LIKE '%{$_REQUEST['kunde']}%'";
+
+		$q = $dbh->query("SELECT a.datum, k.kunde, k.system, a.bundesland, a.feiertag, k.start_soll, k.ende_soll, sm.start, sm.ende, sm.anzahl, sm.bearbeitet,
+								timediff(sm.ende, k.ende_soll) - timediff(sm.start, k.start_soll) as abweichung,
+								case
+								 when woche = 'Mo-Fr' then mofr
+								 when woche = 'Mo-Sa' then mosa
+								 when woche = 'Mo-So' then moso
+								 when woche = 'Di-So' then diso
+								 else 1
+								end * if(sk.status <= 1, 0, 1) * if(sm.anzahl > 0 or (sm.anzahl is null and now() > concat(a.datum, ' ', k.ende_soll)), 1, 0) as fehler,
+								if(sm.anzahl is null and now() > concat(a.datum, ' ', k.ende_soll), 1, 0) as fehlend,
+								ifnull(sk.benutzer, '') as benutzer
+							FROM arbeitstage a
+							INNER JOIN kunden k USING (bundesland)
+							LEFT JOIN status_meldung sm USING (datum, kunde)
+							LEFT JOIN status_kommentar sk ON sm.kommentar_id = sk.id
+							WHERE {$datum} AND {$kunde} AND a.datum <= now()
+							AND k.aktiv = 1
+							ORDER BY a.datum, k.ende_soll");
+		$result = $q->fetchAll(PDO::FETCH_ASSOC);
+
+		if (isset($_REQUEST['events'])) {
+			$color = array("green", "#bb0", "#b80", "#d55", "#c33", "#a00", '?' => "#999");
+
+			$events = array();
+			foreach ($result as $e) {
+				if ($e['anzahl'] != '0') {
+					$event = array();
+					$anzahl = (!is_null($e['anzahl'])) ? $e['anzahl'] : "?";
+					$ende = ($e['ende']) ? $e['ende'] : $e['ende_soll'];
+					$event['title'] = "{$e['kunde']} ({$anzahl})";
+					$event['start'] = "{$e['datum']}T{$ende}";
+					$event['end'] = date("Y-m-d H:i:s", strtotime("+1 hour", strtotime($event['start'])));
+					$event['color'] = ($anzahl > 4) ? "darkred" : $color[$anzahl];
+					$events[] = $event;
+				}
+			}
+			$result = $events;
+		}
+}
 echo json_encode($result);

+ 2 - 0
app/import.bat

@@ -0,0 +1,2 @@
+cd /d "%~dp0"
+php import.php

+ 29 - 16
app/import.php

@@ -26,14 +26,6 @@ for ($m = 1; $m <= $message_count; ++$m) {
 	$date = date("Y-m-d", strtotime($header->MailDate));
 	$result[] = $date . " " . $rec[2] . " - " . $rec[0];
 
-	$body = trim(imap_fetchbody($mbox, $m, '1'));
-	if (substr($body, 0, 4) == "--b2") {
-		$body = "";
-	}
-	array_push($rec, $body);
-
-
-
 	$structure = imap_fetchstructure($mbox, $m);
 	$attachments = array();
 	if (isset($structure->parts) && count($structure->parts)) {
@@ -76,21 +68,42 @@ for ($m = 1; $m <= $message_count; ++$m) {
 		}
 	}
 
-	$a = "";
+	$fehlerbericht = addslashes(trim(imap_fetchbody($mbox, $m, '1')));
+	$info = 0;
+
 	foreach ($attachments as $key => $attachment) {
-		if ($attachment['is_attachment'] && preg_match("/\.bat\.log/", $attachment['filename'])) {
-			$a .= $attachment['attachment'];
+		if ($attachment['is_attachment']) {
+			if ($attachment['filename'] == "info.json") {
+				$info = addslashes($attachment['attachment']);
+			}
+			if ($attachment['filename'] == "fehlerbericht.json") {
+				$fehlerbericht = addslashes($attachment['attachment']);
+			}
 		}
 	}
-	array_push($rec, addslashes($a));
-	$dbh->query("INSERT INTO statusmail (kunde, start, ende, datum, anzahl, fehlerbericht, logdatei) VALUES ('" . implode("','", $rec) . "')");
-
-	imap_delete($mbox, $m);
+	$rec[] = $fehlerbericht;
+
+	$insertQuery = "INSERT INTO status_meldung (kunde, start, ende, datum, anzahl, fehlerbericht) VALUES ('" . implode("','", $rec) . "')";
+	$c = $dbh->query($insertQuery);
+	if ($c) {
+		imap_delete($mbox, $m);
+	} else {
+		$result[] = $insertQuery;
+		$result[] = $dbh->errorInfo();
+	}
 
 	if (!in_array($rec[0], $customers)) {
-		$dbh->query("INSERT INTO kunden (kunde, start_soll, ende_soll, erster_status) VALUES ('{$rec[0]}', '{$rec[1]}', '{$rec[2]}', '{$rec[3]}')");
+		$dbh->query("INSERT INTO kunden (kunde, start_soll, ende_soll, erster_status, system) VALUES ('{$rec[0]}', '{$rec[1]}', '{$rec[2]}', '{$rec[3]}', '?')");
 		array_push($customers, $rec[0]);
 	}
+
+	if ($info) {
+		$q = $dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
+		$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
+		if (!$last || addslashes($last['info']) != $info) {
+			$dbh->query("INSERT INTO kunden_config (kunde, datum, info) VALUES ('{$rec[0]}', '{$rec[3]}', '{$info}')");
+		}
+	}
 }
 imap_expunge($mbox);
 imap_close($mbox);

+ 133 - 88
app/index.html

@@ -1,6 +1,6 @@
 <!doctype html>
 <html class="no-js">
-  <head>
+<head>
     <meta charset="utf-8">
     <title>Fehlerbericht</title>
     <meta name="description" content="">
@@ -9,107 +9,152 @@
     <!-- build:css(.) styles/vendor.css -->
     <!-- bower:css -->
     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
+    <link rel="stylesheet" href="bower_components/fullcalendar/dist/fullcalendar.css" />
     <!-- endbower -->
     <!-- endbuild -->
     <!-- build:css(.tmp) styles/main.css -->
     <link rel="stylesheet" href="styles/main.css">
     <!-- endbuild -->
-      <style type="text/css">
-          .table tr.middle > td, .table tr.middle > th {
-              vertical-align: middle;
-          }
-
-          .btn-darkgreen {
-              color: #ffffff;
-              background-color: #228833;
-              border-color: #228833;
-          }
-          .btn-darkgreen:hover,
-          .btn-darkgreen:focus,
-          .btn-darkgreen:active,
-          .btn-darkgreen.active {
-              background-color: #1d742b;
-              border-color: #185f24;
-              color: #ffffff;
-          }
-          .btn-darkgreen.disabled:hover,
-          .btn-darkgreen.disabled:focus,
-          .btn-darkgreen.disabled:active,
-          .btn-darkgreen.disabled.active,
-          .btn-darkgreen[disabled]:hover,
-          .btn-darkgreen[disabled]:focus,
-          .btn-darkgreen[disabled]:active,
-          .btn-darkgreen[disabled].active,
-          fieldset[disabled] .btn-darkgreen:hover,
-          fieldset[disabled] .btn-darkgreen:focus,
-          fieldset[disabled] .btn-darkgreen:active,
-          fieldset[disabled] .btn-darkgreen.active {
-              background-color: #228833;
-              border-color: #228833;
-          }
-
-      </style>
-  </head>
-  <body ng-app="fehlerberichtApp">
-    <!--[if lt IE 7]>
-      <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
-    <![endif]-->
-
-    <!-- Add your site or application content here -->
-    <div class="container">
-      <div class="header">
+    <style type="text/css">
+        .table tr.middle > td, .table tr.middle > th {
+            vertical-align: middle;
+        }
+
+        .label-A, .label-Autosys {
+            background-color: #ee3;
+            color: #000;
+        }
+
+        .label-E, .label-EDS {
+            background-color: #a33;
+            color: #fff;
+        }
+
+        .label-F, .label-Filaks {
+            background-color: #883;
+            color: #fff;
+        }
+
+        .label-G, .label-GlobalCube {
+            background-color: #57c;
+            color: #fff;
+        }
+
+        .label-L, .label-Light {
+            background-color: #5b5;
+            color: #fff;
+        }
+
+        .label-N, .label-Navision {
+            background-color: #35d;
+            color: #fff;
+        }
+
+        .label-O, .label-Optima {
+            background-color: #050;
+            color: #fff;
+        }
+
+        .closed-tab {
+            display: none;
+        }
+
+        .caret-up {
+            border-bottom: 10px solid #000000;
+            border-left: 6px solid rgba(0, 0, 0, 0);
+            border-right: 6px solid rgba(0, 0, 0, 0);
+            content: "";
+            display: inline-block;
+            height: 0;
+            vertical-align: top;
+            width: 0;
+        }
+
+        .red {
+            color: #cc0000;
+        }
+    </style>
+</head>
+<body ng-app="fehlerberichtApp">
+<!--[if lt IE 7]>
+<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to
+    improve your experience.</p>
+<![endif]-->
+
+<!-- Add your site or application content here -->
+<div class="container-fluid">
+    <div class="header">
         <ul class="nav nav-pills pull-right">
-          <li><a ng-href="#">Übersicht</a></li>
-          <li><a ng-href="#/overview">Konfiguration</a></li>
+            <li><a ng-href="#">Übersicht</a></li>
+            <li><a ng-href="#/calendar">Kalender</a></li>
+            <li><a ng-href="#/customers">Kunden</a></li>
+            <li><a ng-href="#/config">Konfiguration</a></li>
+            <li><a ng-href="#/stats/Altermann">Statistik</a></li>
         </ul>
-        <h3 class="text-muted">Fehlerbericht</h3>
-      </div>
-
-      <div ng-view=""></div>
+        <h3 class="text-muted"><a ng-href="#">Fehlerbericht</a></h3>
+    </div>
 
+    <div class="row">
+        <div ng-view="" class="col-md-12"></div>
     </div>
+</div>
 
 
-    <!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
-     <script>
-       (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-       (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-       m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-       })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+<!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
+<script>
+    (function (i, s, o, g, r, a, m) {
+        i['GoogleAnalyticsObject'] = r;
+        i[r] = i[r] || function () {
+            (i[r].q = i[r].q || []).push(arguments)
+        }, i[r].l = 1 * new Date();
+        a = s.createElement(o),
+                m = s.getElementsByTagName(o)[0];
+        a.async = 1;
+        a.src = g;
+        m.parentNode.insertBefore(a, m)
+    })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
 
-       ga('create', 'UA-XXXXX-X');
-       ga('send', 'pageview');
-    </script>
+    ga('create', 'UA-XXXXX-X');
+    ga('send', 'pageview');
+</script>
 
-    <!-- build:js(.) scripts/oldieshim.js -->
-    <!--[if lt IE 9]>
-    <script src="bower_components/es5-shim/es5-shim.js"></script>
-    <script src="bower_components/json3/lib/json3.min.js"></script>
-    <![endif]-->
-    <!-- endbuild -->
+<!-- build:js(.) scripts/oldieshim.js -->
+<!--[if lt IE 9]>
+<script src="bower_components/es5-shim/es5-shim.js"></script>
+<script src="bower_components/json3/lib/json3.min.js"></script>
+<![endif]-->
+<!-- endbuild -->
 
-    <!-- build:js(.) scripts/vendor.js -->
-    <!-- bower:js -->
-    <script src="bower_components/jquery/dist/jquery.js"></script>
-    <script src="bower_components/angular/angular.js"></script>
-    <script src="bower_components/json3/lib/json3.js"></script>
-    <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
-    <script src="bower_components/angular-resource/angular-resource.js"></script>
-    <script src="bower_components/angular-cookies/angular-cookies.js"></script>
-    <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
-    <script src="bower_components/angular-animate/angular-animate.js"></script>
-    <script src="bower_components/angular-touch/angular-touch.js"></script>
-    <script src="bower_components/angular-route/angular-route.js"></script>
-    <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
-    <script src="bower_components/moment/moment.js"></script>
-    <script src="bower_components/underscore/underscore.js"></script>
-    <!-- endbower -->
-    <!-- endbuild -->
+<!-- build:js(.) scripts/vendor.js -->
+<!-- bower:js -->
+<script src="bower_components/jquery/dist/jquery.js"></script>
+<script src="bower_components/angular/angular.js"></script>
+<script src="bower_components/json3/lib/json3.js"></script>
+<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
+<script src="bower_components/angular-resource/angular-resource.js"></script>
+<script src="bower_components/angular-cookies/angular-cookies.js"></script>
+<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
+<script src="bower_components/angular-animate/angular-animate.js"></script>
+<script src="bower_components/angular-touch/angular-touch.js"></script>
+<script src="bower_components/angular-route/angular-route.js"></script>
+<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+<script src="bower_components/flot/jquery.flot.js"></script>
+<script src="bower_components/flot/jquery.flot.pie.js"></script>
+<script src="bower_components/moment/moment.js"></script>
+<script src="bower_components/moment/locale/de.js"></script>
+<script src="bower_components/fullcalendar/dist/fullcalendar.js"></script>
+<script src="bower_components/fullcalendar/dist/lang/de.js"></script>
+<script src="bower_components/underscore/underscore.js"></script>
+<!-- endbower -->
+<!-- endbuild -->
 
-        <!-- build:js({.tmp,app}) scripts/scripts.js -->
-        <script src="scripts/app.js"></script>
-        <script src="scripts/controllers/main.js"></script>
-        <script src="scripts/controllers/overview.js"></script>
-        <!-- endbuild -->
+<!-- build:js({.tmp,app}) scripts/scripts.js -->
+<script src="scripts/app.js"></script>
+<script src="scripts/controllers/calendar.js"></script>
+<script src="scripts/controllers/config.js"></script>
+<script src="scripts/controllers/customers.js"></script>
+<script src="scripts/controllers/overview.js"></script>
+<script src="scripts/controllers/stats.js"></script>
+<!-- endbuild -->
 </body>
 </html>

+ 52 - 27
app/scripts/app.js

@@ -1,29 +1,54 @@
-'use strict';
+(function () {
+    'use strict';
 
-/**
- * @ngdoc overview
- * @name fehlerberichtApp
- * @description
- * # fehlerberichtApp
- *
- * Main module of the application.
- */
-angular
-    .module('fehlerberichtApp', [
-        'ngAnimate',
-        'ngCookies',
-        'ngResource',
-        'ngRoute',
-        'ngSanitize',
-        'ngTouch'
-    ])
-    .config(function ($routeProvider) {
-        $routeProvider
-            .when('/', {
-                templateUrl: 'views/overview.html',
-                controller: 'OverviewCtrl'
-            })
-            .otherwise({
-                redirectTo: '/'
-            });
+    angular
+        .module('fehlerberichtApp', [
+            'ngAnimate',
+            'ngCookies',
+            'ngResource',
+            'ngRoute',
+            'ngSanitize',
+            'ngTouch'
+        ])
+        .config(function ($routeProvider) {
+            $routeProvider
+                .when('/overview/:customer/:date/:status', {
+                    templateUrl: 'views/overview.html',
+                    controller: 'OverviewCtrl'
+                })
+                .when('/calendar', {
+                    templateUrl: 'views/calendar.html',
+                    controller: 'CalendarCtrl'
+                })
+                .when('/customers', {
+                    templateUrl: 'views/customers.html',
+                    controller: 'CustomersCtrl'
+                })
+                .when('/stats/:customer', {
+                    templateUrl: 'views/stats.html',
+                    controller: 'StatsCtrl'
+                })
+                .when('/config/:customer/:date', {
+                    templateUrl: 'views/config.html',
+                    controller: 'ConfigCtrl'
+                })
+                .when('/config', {
+                    templateUrl: 'views/config.html',
+                    controller: 'ConfigCtrl'
+                })
+                .otherwise({
+                    redirectTo: '/overview/all/today/errors'
+                });
+        });
+
+    moment.locale('de', {
+        calendar: {
+            lastDay: "[Gestern]",
+            lastWeek: "[letzten] dddd",
+            nextDay: "[Morgen]",
+            nextWeek: "dddd",
+            sameDay: "[Heute]",
+            sameElse: "L"
+        }
     });
+})();

+ 75 - 0
app/scripts/controllers/calendar.js

@@ -0,0 +1,75 @@
+'use strict';
+
+angular.module('fehlerberichtApp')
+    .controller('CalendarCtrl', function ($scope, $http) {
+        var webservice = 'http://rbs06/fehlerbericht/db.php?';
+
+        $().ready(function() {
+
+            // page is now ready, initialize the calendar...
+
+            $('#calendar').fullCalendar({
+                'weekNumbers': true,
+                'header': {
+                    left:   'title',
+                    center: '',
+                    right:  'month basicWeek agendaDay today prev,next'
+                },
+                'events': {
+                    'url': webservice + 'a=liste&events=1'
+                }
+                /*
+                events: [
+                    {
+                        title: 'Reisacher (1)',
+                        start: '2014-11-01T06:03:00',
+                        color: 'yellow',
+                        textColor: 'black'
+                    },
+                    {
+                        title: 'Arndt (3)',
+                        start: '2014-11-07T09:10:00',
+                        color: 'red'
+                    },
+                    {
+                        title: 'Nauheim (2)',
+                        start: '2014-11-11T07:00:00',
+                        color: 'orange'
+                    },
+                    {
+                        title: 'Ulmen (2)',
+                        start: '2014-11-12T10:30:00',
+                        color: 'orange'
+                    },
+                    {
+                        title: 'Auto Nova (5)',
+                        start: '2014-11-12T12:00:00',
+                        color: 'darkred'
+                    },
+                    {
+                        title: 'Bunk (1)',
+                        start: '2014-11-12T14:30:00',
+                        color: 'yellow',
+                        textColor: 'black'
+                    },
+                    {
+                        title: 'Lehr (3)',
+                        start: '2014-11-12T17:30:00',
+                        color: 'red'
+                    },
+                    {
+                        title: 'Boettche (1)',
+                        start: '2014-11-12T20:00:00',
+                        color: 'yellow',
+                        textColor: 'black'
+                    },
+                    {
+                        title: 'Voss und Voss (2)',
+                        start: '2014-11-13T07:00:00',
+                        color: 'orange'
+                    }
+                ] */
+            });
+
+        });
+    });

+ 56 - 0
app/scripts/controllers/config.js

@@ -0,0 +1,56 @@
+'use strict';
+
+angular.module('fehlerberichtApp')
+    .controller('ConfigCtrl', function ($scope, $http, $routeParams) {
+        var webservice = 'http://rbs06/fehlerbericht/db.php?';
+
+        $scope.current = {
+            'kunde': $routeParams.customer,
+            'datum': $routeParams.date
+        };
+
+        $scope.data = {};
+        $scope.domain = {};
+        $scope.filter = {};
+
+        $scope.options = {
+            'kunde': [],
+            'datum': {}
+        };
+
+        $scope.dateFormat = function (date) {
+            var d = moment(date, 'YYYY-MM-DD');
+            if (d.isValid()) {
+                return d.format('dd, DD.MM.YYYY');
+            }
+            return date;
+        };
+
+        $scope.refresh = function () {
+            $scope.data = {};
+            $http.get(webservice + 'a=config&kunde=' + $scope.current.kunde + '&datum=' + $scope.current.datum).success(function (data) {
+                $scope.options.datum = data.options;
+                $scope.options.datum[undefined] = [];
+                $scope.options.kunde = _.keys(data.options);
+                if (data.current) {
+                    $scope.current.datum = data.current.datum;
+                    $scope.options.tabelle = _.keys(data.current.info);
+                    $scope.current.tabelle = _.first($scope.options.tabelle);
+                    $scope.data = data.current.info;
+
+                    _.each($scope.data, function (table, t) {
+                        $scope.domain[t] = {};
+                        $scope.filter[t] = {};
+                        _.each(table[0], function (col, k) {
+                            $scope.domain[t][k] = _.uniq(_.pluck(table, k));
+                            $scope.filter[t][k] = '';
+                        });
+                    });
+
+                }
+                $scope.options.datum[undefined] = [];
+            });
+        };
+
+        $scope.refresh();
+    });

+ 91 - 0
app/scripts/controllers/customers.js

@@ -0,0 +1,91 @@
+'use strict';
+
+angular.module('fehlerberichtApp')
+    .controller('CustomersCtrl', function ($scope, $http) {
+        var webservice = 'http://rbs06/fehlerbericht/db.php?';
+
+        $scope.info = [];
+        $scope.error = -1;
+
+        $scope.domain = {
+            'aktiv': {
+                '1': 'Aktiv',
+                '0': 'Inaktiv'
+            },
+            'system': [
+                '?',
+                'Autosys',
+                'Autosys-Light',
+                'EDS',
+                'Filaks',
+                'GlobalCube',
+                'Light',
+                'Navision',
+                'Optima'
+            ],
+            'woche': [
+                'Mo-Fr',
+                'Mo-Sa',
+                'Mo-So',
+                'Di-So'
+            ],
+            'bundesland': {
+                'AT': 'Österreich',
+                'BW': 'Baden-Württemberg',
+                'BY': 'Bayern',
+                'BE': 'Berlin',
+                'BB': 'Brandenburg',
+                'HB': 'Bremen',
+                'HH': 'Hamburg',
+                'HE': 'Hessen',
+                'MV': 'Mecklenburg-Vorpommern',
+                'NI': 'Niedersachsen',
+                'NW': 'Nordrhein-Westfalen',
+                'RP': 'Rheinland-Pfalz',
+                'SL': 'Saarland',
+                'SN': 'Sachsen',
+                'ST': 'Sachsen-Anhalt',
+                'SH': 'Schleswig-Holstein',
+                'TH': 'Thüringen'
+            }
+        };
+
+        $scope.kunden = [];
+
+        $scope.current = {
+            'zeile' : {},
+            'fehler': {}
+        };
+
+        $scope.Filter = {
+            'aktiv': '1',
+            'kunde': '',
+            'system': ''
+        };
+
+        $scope.removeItem = function (index) {
+            // Beispiel
+            $scope.Bestellungen = $scope.Bestellungen.splice(index, 1);
+        };
+
+        $scope.refresh = function () {
+            $http.get(webservice + 'a=kunden').success(function (data) {
+                $scope.kunden = data;
+            });
+        };
+
+        $scope.refresh();
+
+        $scope.firstChar = function (t) {
+            if (t === '') {
+                return '?';
+            }
+            return t.substring(0, 1);
+        };
+
+        $scope.save = function () {
+            $http.put(webservice + 'a=kunden', $scope.kunden).success(function (data) {
+                $scope.kunden = data;
+            });
+        };
+    });

+ 0 - 89
app/scripts/controllers/main.js

@@ -9,96 +9,7 @@ angular.module('fehlerberichtApp').filter("euro", function () {
     };
 });
 
-/**
- * @ngdoc function
- * @name kasseApp.controller:MainCtrl
- * @description
- * # MainCtrl
- * Controller of the kasseApp
- */
 angular.module('fehlerberichtApp')
     .controller('MainCtrl', function ($scope) {
-        $scope.Produkte = [
-            {
-                "Produkt": 0,
-                "Anzahl": 1,
-                "Bezeichnung": "Steak mit Pommes",
-                "Extras": {
-                    "Jaeger": true,
-                    "Zwiebel": false
-                },
-                "EP": 5.5
-            },
-            {
-                "Produkt": 1,
-                "Anzahl": 1,
-                "Bezeichnung": "Steak mit Brot",
-                "Extras": {
-                    "Jaeger": true,
-                    "Zwiebel": false
-                },
-                "EP": 4.5
-            },
-            {
-                "Produkt": 2,
-                "Anzahl": 1,
-                "Bezeichnung": "Hackbraten mit Pommes",
-                "Extras": {
-                    "Jaeger": false,
-                    "Zwiebel": true
-                },
-                "EP": 5.5
-            },
-            {
-                "Produkt": 3,
-                "Anzahl": 1,
-                "Bezeichnung": "Hackbraten mit Brot",
-                "Extras": {
-                    "Jaeger": false,
-                    "Zwiebel": true
-                },
-                "EP": 4.5
-            },
-            {
-                "Produkt": 4,
-                "Anzahl": 1,
-                "Bezeichnung": "Portion Pommes",
-                "EP": 3.0
-            }
-        ];
 
-        $scope.Rechnung = window.localStorage.getItem("Rechnung");
-        $scope.OffeneBestellungen = window.localStorage.getItem("OffeneBestellungen");
-        $scope.Bestellung = [];
-
-        $scope.Anzahl = function () {
-            return _.reduce($scope.Bestellung, function (sum, b) { return sum + b.Anzahl; }, 0);
-        };
-
-        $scope.Summe = function () {
-            return _.reduce($scope.Bestellung, function (sum, b) { return sum + b.Anzahl * b.EP; }, 0);
-        };
-
-        $scope.addItem = function (num) {
-            $scope.Bestellung.push($.extend(true, {}, $scope.Produkte[num]));
-        };
-
-        $scope.removeItem = function (item) {
-            $scope.Bestellung = _.without($scope.Bestellung, item);
-        };
-
-        $scope.checkOut = function () {
-            $scope.OffeneBestellungen.push({ "Rechnung": $scope.Rechnung, "Bestellung":  $scope.Bestellung });
-            $scope.Bestellung = [];
-            $scope.Rechnung = parseInt($scope.Rechnung, 10) + 1;
-            window.localStorage.setItem("Rechnung", $scope.Rechnung);
-            window.localStorage.setItem("OffeneBestellungen", JSON.stringify($scope.OffeneBestellungen));
-        };
-
-        if ($scope.OffeneBestellungen === null) {
-            $scope.Rechnung = 1;
-            $scope.OffeneBestellungen = [];
-        } else {
-            $scope.OffeneBestellungen = JSON.parse($scope.OffeneBestellungen);
-        }
     });

+ 307 - 31
app/scripts/controllers/overview.js

@@ -8,65 +8,159 @@
  * Controller of the fehlerberichtApp
  */
 angular.module('fehlerberichtApp')
-    .controller('OverviewCtrl', function ($scope, $http) {
-        var webservice = 'http://rbs06/GlobalCube/Fehlerbericht/app/db.php?';
+    .controller('OverviewCtrl', function ($scope, $http, $routeParams, $interval) {
+        var webservice = 'http://rbs06/fehlerbericht/db.php?';
 
-        $scope.info = [];
-        $scope.error = -1;
+        $scope.error = {
+            'level': -1,
+            'info': [],
+            'message': ""
+        };
+
+        $scope.domain = {
+            'bearbeitet': {
+                '0': "angesehen",
+                '1': "behoben",
+                '2': "übernommen",
+                '3': "Rücksprache mit Kunde",
+                '4': "Serverproblem",
+                '5': "Prozess läuft",
+                '6': "ignoriert / egal"
+            },
+            'comment': {
+                '0': "glyphicon-eye-open",
+                '1': "glyphicon-ok",
+                '2': "glyphicon-user",
+                '3': "glyphicon-earphone",
+                '4': "glyphicon-flash",
+                '5': "glyphicon-refresh",
+                '6': "glyphicon-remove"
+            },
+            'statusfilter': {
+                '2': 'nicht behoben',
+                '5': 'läuft',
+                '6': 'ignoriert'
+            },
+            'fehler': {
+                '0': "okay",
+                '1': "fehlerhaft"
+            },
+            'system': [
+                '?',
+                'Autosys',
+                'Autosys-Light',
+                'EDS',
+                'Filaks',
+                'GlobalCube',
+                'Light',
+                'Navision',
+                'Optima'
+            ],
+            'datum': {},
+            'kunde': {},
+            'status': {
+                'errors': '1',
+                'all': '',
+                'missing': '',
+                'flawless': '0'
+            },
+            'fehlend': {
+                '1': 'fehlt',
+                '0': 'vorhanden'
+            },
+            'date': {
+                'all': '',
+                'today': moment().format('YYYY-MM-DD'),
+                'yesterday':  moment().subtract(1, 'days').format('YYYY-MM-DD')
+            },
+            'benutzer': []
+        };
 
         $scope.benutzer = window.localStorage.getItem("Benutzer");
 
         $scope.overview = [];
+        $scope.comments = {};
 
         $scope.datum = [];
-        $scope.kunden = [];
 
         $scope.current = {
-            'kunde' : '',
-            'datum': '',
-            'fehler': {}
+            'zeile' : {},
+            'fehler': {},
+            'details': null,
+            'status': 2,
+            'kommentar': {}
         };
 
         $scope.Filter = {
-            'datum': moment().format('YYYY-MM-DD'),
-            'kunde': '',
-            'fehler': '1'
+            'datum': (moment($routeParams.date).isValid()) ? moment($routeParams.date).format('YYYY-MM-DD') : $scope.domain.date[$routeParams.date],
+            'kunde': ($routeParams.customer === 'all') ? '' : $routeParams.customer,
+            'fehler': $scope.domain.status[$routeParams.status],
+            'fehlend': ($routeParams.status === 'missing') ? '1' : '',
+            'system': '',
+            'benutzer': ''
         };
 
+        $scope.Predicate = (function () {
+            if ($routeParams.customer !== 'all') {
+                return 'datum';
+            }
+            if ($routeParams.date === 'today' && $routeParams.status === 'errors') {
+                    return 'ende_soll';
+            }
+            return ['kunde','datum'];
+        })();
+
+        $scope.Reverse = ($routeParams.customer !== 'all');
+
+        $scope.SearchText = '';
+
         $scope.removeItem = function (index) {
+            // Beispiel
             $scope.Bestellungen = $scope.Bestellungen.splice(index, 1);
         };
 
+        $http.get(webservice + 'a=benutzer').success(function (data) {
+            $scope.domain.benutzer = _.unique(_.pluck(data, 'benutzer'));
+        });
+
+
         $scope.refresh = function () {
-            $http.get(webservice).success(function (data) {
+            $http.get(webservice + 'a=liste&kunde=' + $scope.Filter.kunde + '&datum=' + $scope.Filter.datum).success(function (data) {
                 $scope.overview = data;
-                $scope.datum = _.uniq(_.pluck(data, 'datum'));
+                //$scope.domain.benutzer = _.unique(_.pluck(data, 'benutzer'));
             });
-
-            $http.get(webservice + 'kunden=1').success(function (data) {
-                $scope.kunden = data;
+            $http.get(webservice + 'a=kommentar&kunde=' + $scope.Filter.kunde + '&datum=' + $scope.Filter.datum).success(function (data) {
+                $scope.comments = _.groupBy(data, 'kunde');
             });
+
         };
 
         $scope.importData = function () {
+            $scope.error.level = 0;
+            $scope.error.message = "Aktualisierung läuft!";
             $http.get('http://rbs06/GlobalCube/Fehlerbericht/app/import.php').success(function (data) {
                 if (Array.isArray(data)) {
-                    $scope.info = data;
+                    $scope.error.info = data;
                     if (data.length === 0) {
-                        $scope.error = -1;
+                        $scope.error.level = 0;
+                        $scope.error.message = "Keine neuen Datensätze!";
                     } else {
-                        $scope.error = 0;
+                        $scope.error.message = "Neue Datensätze:";
+                        $scope.error.level = 0;
                         $scope.refresh();
                     }
                 } else {
-                    $scope.info[0] = data;
-                    $scope.error = 1;
+                    $scope.error.info = [];
+                    $scope.error.level = 1;
+                    $scope.error.message = data;
                 }
             });
         };
 
         $scope.refresh();
 
+        $interval($scope.refresh, 5 * 60 * 1000);
+
         $scope.minuten = function (t) {
             var faktor, m, mins;
             if (!t) {
@@ -82,22 +176,184 @@ angular.module('fehlerberichtApp')
             return mins + " Min.";
         };
 
+        $scope.timeDiffStart = function (z) {
+
+            if (z.start === null) {
+                return '';
+            }
+            var duration = moment.duration(z.start, 'HH:mm:ss').subtract(moment(z.start_soll, 'HH:mm:ss')).asMinutes();
+            if (duration !== 0) {
+                var plus = (duration > 0) ? '+' : '';
+                return plus + duration + ' Minuten';
+            }
+            return '';
+        };
+
+        $scope.timeDiff = function (z) {
+
+            if (z.start === null) {
+                return '';
+            }
+            var duration = moment.duration(z.ende, 'HH:mm:ss').subtract(moment(z.ende_soll, 'HH:mm:ss')).asMinutes() - moment.duration(z.start, 'HH:mm:ss').subtract(moment(z.start_soll, 'HH:mm:ss')).asMinutes();
+            if (duration !== 0) {
+                var plus = (duration > 0) ? '+' : '';
+                return '(' + plus + duration + ' Min.)';
+            }
+            return '';
+        };
+
         $scope.dateFormat = function (date) {
-            var d = moment(date);
+            var d = moment(date, 'YYYY-MM-DD');
             if (d.isValid()) {
-                return moment(date).format('DD.MM.YYYY');
+                if (date === $scope.domain.date.today) {
+                    return 'Heute';
+                }
+                if (date === $scope.domain.date.yesterday) {
+                    return 'Gestern';
+                }
+                return d.format('dd, DD.MM.YYYY');
             }
             return date;
         };
 
-        $scope.setCurrent = function (zeile) {
-            $scope.current.kunde = zeile.kunde;
-            $scope.current.datum = zeile.datum;
+        $scope.timeFormat = function (t) {
+            var d = moment(t, 'YYYY-MM-DD HH:mm:ss');
+            if (d.isValid()) {
+                return d.format('HH:mm:ss');
+            }
+            return t;
+        };
 
-            $http.get(webservice + 'kunde=' + zeile.kunde + '&datum=' + zeile.datum).success(function (data) {
+        $scope.mailFormat = function (t) {
+            if (t === undefined) {
+                return '';
+            }
+            return _.map(t.split(';'), function (e) { return '<a href="mailto:' + e + '">' + e + '</a>'; }).join('<br/>');
+        };
+
+        $scope.left = function (text, length) {
+            if (text.length === 0) {
+                return '?';
+            }
+            return text.substring(0, length);
+        };
+
+
+        $scope.errorCount = function (e) {
+            if (e.Errors.length === 0 || e.Errors.length === 1 && e.Errors[0] === '') {
+                return $scope.daysCount(e);
+            }
+            var type = 'Info';
+            if (e.ErrorLevel < 3) {
+                type = 'Fehler';
+            }
+            return e.Errors.length + ' ' + type;
+        };
+
+        $scope.daysCount = function (e) {
+            if (e.LastChangedDays === 0) {
+                return '0';
+            }
+            return e.LastChangedDays + ' Tage alt';
+        };
+
+        $scope.errorLevel = function (e) {
+            return e.ErrorLevel <= 2 || e.Name.indexOf('bat') > -1 || e.LastChangedDays >= 3;
+        };
+
+        $scope.setCurrent = function (row) {
+            $scope.current.zeile = row;
+            $scope.current.fehler = {};
+            $scope.current.details = null;
+
+            $scope.current.status = 2;
+            $scope.current.kommentar = {};
+            $scope.current.template = {
+                'id': '',
+                'datum': row.datum,
+                'kunde': row.kunde,
+                'start': row.start,
+                'benutzer': $scope.benutzer,
+                'fehler': (row.anzahl === null) ? 0 : parseInt(row.anzahl, 10),
+                'status': '0',
+                'kommentar': ''
+            };
+
+
+            $http.get(webservice + 'a=fehlerbericht&kunde=' + $scope.current.zeile.kunde + '&datum=' + $scope.current.zeile.datum + '&start=' + $scope.current.zeile.start).success(function (data) {
                 $scope.current.fehler = data;
-                if (data.benutzer === '') {
-                    $scope.current.fehler.benutzer = $scope.benutzer;
+
+                if (data.benutzer === '' || data.benutzer !== $scope.benutzer) {
+                    $scope.current.kommentar = $scope.current.template;
+                } else {
+                    $scope.current.kommentar = $scope.comments[data.kunde][0];
+                    $scope.current.kommentar.fehler = parseInt($scope.current.kommentar.fehler, 10);
+                }
+                data.fehlerbericht = _.sortBy(data.fehlerbericht, function(e) { return moment(e.Modified); });
+                data.weitere = _.chain(data.fehlerbericht).reject($scope.errorLevel).groupBy(function (e) { return e.Type; }).value();
+
+                var duration = _.map(_.filter(data.fehlerbericht, function (e) { return e.Summary !== null && e.Summary.Duration !== null && e.Summary.Duration >= '00:01:00'; }), function(e) { return { 'label': e.Type + ': ' + e.Name + ' (' + e.Summary.Duration + ')', 'data':  moment.duration(e.Summary.Duration, 'HH:mm:ss').asMinutes() }; });
+
+                $.plot('#duration', duration, {
+                    series: {
+                        pie: {
+                            show: true,
+                            radius: 0.8
+                        }
+                    },
+                    legend: {
+                        show: true
+                    }
+                });
+            });
+        };
+
+        $scope.getComments = function (zeile) {
+            if ($scope.comments[zeile.kunde]) {
+                if (zeile.fehlend === '1') {
+                    return $scope.comments[zeile.kunde];
+                }
+                var newComments = _.filter($scope.comments[zeile.kunde], function (row) { return row.datum === zeile.datum; });
+                if (newComments.length > 0) {
+                    return newComments;
+                }
+            }
+            return false;
+        };
+
+        $scope.getCommentIcon = function (c) {
+            var c0 = c;
+            if (c.length > 0) {
+                c0 = c[0];
+            }
+            if (c0.status) {
+                return $scope.domain.comment[c0.status];
+            }
+            return "glyphicon-question-sign";
+        };
+
+
+        $scope.shortFilename = function(filename) {
+            if (filename !== undefined && filename.length > 0 && filename.indexOf("\\") >= 0) {
+                return filename.substring(filename.lastIndexOf("\\") + 1);
+            }
+            return filename;
+        };
+
+        $scope.showDetails = function (entry) {
+            $scope.current.details = entry;
+
+            var duration = _.map(_.filter(entry.Sources, function(e) { return e.Duration > '00:01:00'; }), function(e) { return { 'label': $scope.shortFilename(e.Filename) + ' (' + e.Duration + ')', 'data':  Math.round(moment.duration(e.Duration, 'HH:mm:ss').asMinutes()) }; });
+
+            $.plot('#duration_details', duration, {
+                series: {
+                    pie: {
+                        show: true,
+                        radius: 0.8
+                    }
+                },
+                legend: {
+                    show: true
                 }
             });
         };
@@ -108,8 +364,28 @@ angular.module('fehlerberichtApp')
         };
 
         $scope.saveComments = function () {
-            $http.post(webservice + 'kunde=' + $scope.current.kunde + '&datum=' + $scope.current.datum, $scope.current.fehler).success(function (data) {
-                window.alert('Hat geklappt!');
+            $http.put(webservice + 'a=kommentar&id=' + $scope.current.kommentar.id, $scope.current.kommentar).success(function (data) {
+                $scope.comments = data;
+
+                if ($scope.current.kommentar.id === '') {
+                    $scope.refresh();
+                }
+            });
+        };
+
+        $scope.saveStartTime = function (zeile) {
+            $http.put(webservice + 'a=zeit&kunde=' + zeile.kunde + '&start_soll=' + zeile.start + '&ende_soll=' + zeile.ende_soll).success(function (data) {
+                zeile.start_soll = zeile.start;
             });
         };
+
+        $scope.saveEndTime = function (zeile) {
+            $http.put(webservice + 'a=zeit&kunde=' + zeile.kunde + '&start_soll=' + zeile.start_soll + '&ende_soll=' + zeile.ende).success(function (data) {
+                zeile.ende_soll = zeile.ende;
+            });
+        };
+
+        $scope.statusFilter = function (row) {
+            return (row.status >= $scope.current.status);
+        };
     });

+ 62 - 0
app/scripts/controllers/stats.js

@@ -0,0 +1,62 @@
+(function () {
+    'use strict';
+
+    angular.module('fehlerberichtApp')
+        .controller('StatsCtrl', function ($scope, $http, $routeParams) {
+            var webservice = 'http://rbs06/fehlerbericht/db.php?';
+
+            $scope.data = {};
+            $scope.summary = {};
+            $scope.options = {};
+            $scope.customer = $routeParams.customer;
+
+            $scope.refresh = function () {
+                $scope.data = {};
+                $scope.summary = {};
+                $http.get(webservice + 'a=config&datum=current&kunde=' + $scope.customer).success(function (data) {
+                    if (data.current) {
+                        $scope.options.customer = _.keys(data.options);
+                        $scope.data = data.current.info;
+
+                        var reports = _.filter($scope.data.reports, function (row) {
+                            return row.Datei.match(/ver/i) === null && row.GIF === 'N';
+                        });
+                        $scope.summary = {
+                            '1. Portale': _.uniq(_.pluck(reports, 'Datei')),
+                            '1.1 Analyse-User': _.uniq(_.pluck(_.filter(reports, function (row) {
+                                return row.PDF === 'N';
+                            }), 'Benutzer')),
+                            '1.2 PDF-User': _.uniq(_.pluck(_.filter(reports, function (row) {
+                                return row.PDF === 'J';
+                            }), 'Benutzer')),
+                            '1.3 Ebenen': _.uniq(_.pluck(reports, 'Struktur')),
+
+                            '2. Versandintervalle': _.uniq(_.pluck($scope.data.versand, 'Datei')),
+                            '2.1 Empfänger': _.uniq(_.sortBy(_.pluck($scope.data.versand, 'Empfaenger'), function (row) {
+                                return row;
+                            })),
+                            '2.2 Reports': _.uniq(_.sortBy(_.pluck($scope.data.versand, 'Report'), function (row) {
+                                return row;
+                            })),
+
+                            '3. Cubes': _.uniq(_.sortBy(_.filter(_.pluck($scope.data.ppr, 'Cube'), function (row) {
+                                return row !== '';
+                            }), function (row) {
+                                return row;
+                            })),
+                            '4. Fehlende Reports': _.uniq(_.pluck(_.filter($scope.data.ppr, function (row) {
+                                return row.PPR === 'fehlt' && row.Typ === 'PPR';
+                            }), 'Report'))
+                        };
+                    }
+                });
+            };
+
+            $scope.refresh();
+
+            $scope.test = function (v) {
+                return v.match(/(test|global-cube)/i);
+            };
+        }
+    );
+})();

+ 3 - 0
app/views/calendar.html

@@ -0,0 +1,3 @@
+<div class="col-md-7" id='calendar'>
+
+</div>

+ 45 - 0
app/views/config.html

@@ -0,0 +1,45 @@
+<table class="table table-bordered" style="width: auto;">
+    <tr>
+        <td>
+            <label>Kunde:
+                <select class="form-control" ng-model="current.kunde" ng-options="k for k in options.kunde" ng-change="data={}"></select>
+            </label>
+        </td>
+        <td>
+            <label>Datum:
+                <select class="form-control" ng-model="current.datum" ng-options="dateFormat(v) for v in options.datum[current.kunde]" ng-change="refresh()"></select>
+            </label>
+        </td>
+        <td>
+            <label>Tabelle:
+                <select class="form-control" ng-model="current.tabelle" ng-options="v for v in options.tabelle"></select>
+            </label>
+        </td>
+    </tr>
+</table>
+
+<table class="table table-bordered table-condensed table-striped" style="width: auto;">
+    <tr>
+        <th></th>
+        <th ng-repeat="(col, v) in domain[current.tabelle]">{{col}}</th>
+    </tr>
+    <tr>
+        <td></td>
+        <td ng-repeat="(col, dom) in domain[current.tabelle]">
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{filter[current.tabelle][col]||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="filter[current.tabelle][col]=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="e in dom"><a ng-click="filter[current.tabelle][col]=e">{{e}}</a></li>
+                </ul>
+            </div>
+        </td>
+    </tr>
+    <tr ng-repeat="row in data[current.tabelle] | filter: filter[current.tabelle]">
+        <th>{{$index+1}}</th>
+        <td ng-repeat="col in row">
+            {{col}}
+        </td>
+    </tr>
+</table>

+ 264 - 0
app/views/customers.html

@@ -0,0 +1,264 @@
+<button type="button" class="btn btn-info" ng-click="save()">
+    <span class="glyphicon glyphicon-floppy-disk"></span> Speichern
+</button>
+<br/><br/>
+<form role="form">
+<table class="table table-bordered table-striped" style="width: auto;">
+    <tr>
+        <th style="width: 230px;">Kunde</th>
+        <th style="width: 130px;">Aktiv</th>
+        <th style="width: 180px;">System</th>
+        <th style="width: 140px;">Start</th>
+        <th style="width: 140px;">Ende</th>
+        <th style="width: 190px;">Erster Bericht</th>
+        <th style="width: 130px;">Arbeitstage</th>
+        <th style="width: 250px;">Bundesland</th>
+        <th style="width: 100px;">PLZ</th>
+        <th style="width: 200px;">Ort</th>
+        <th style="width: 220px;">Optionen</th>
+    </tr>
+    <tr>
+        <td><input ng-model="Filter.kunde"/></td>
+        <td>
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.aktiv[Filter.aktiv]||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="Filter.aktiv=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="(key,val) in domain.aktiv"><a ng-click="Filter.aktiv=key">{{val}}</a></li>
+                </ul>
+            </div>
+        </td>
+        <td>
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.system||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="Filter.system=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="val in domain.system"><a ng-click="Filter.system=val">{{val}}</a></li>
+                </ul>
+            </div>
+        </td>
+        <td></td>
+        <td></td>
+        <td></td>
+        <td>
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.woche||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="Filter.woche=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="val in domain.woche"><a ng-click="Filter.woche=val">{{val}}</a></li>
+                </ul>
+            </div>
+        </td>
+        <td>
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.bundesland[Filter.bundesland]||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="Filter.bundesland=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="(key,val) in domain.bundesland"><a ng-click="Filter.bundesland=key">{{val}}</a></li>
+                </ul>
+            </div>
+        </td>
+        <td></td>
+        <td></td>
+        <td></td>
+    </tr>
+
+    <tr ng-repeat="zeile in kunden | filter:Filter">
+        <td><strong>{{zeile.kunde}}</strong></td>
+        <td><select class="form-control" ng-model="zeile.aktiv" ng-options="k as v for (k,v) in domain.aktiv"></select></td>
+        <td>
+            <div class="input-group">
+                <div class="input-group-addon label-{{zeile.system}}">{{firstChar(zeile.system)}}</div>
+                <select class="form-control" ng-model="zeile.system" ng-options="v for v in domain.system"></select>
+            </div>
+        </td>
+        <td><input class="form-control" type="time" ng-model="zeile.start_soll"/></td>
+        <td><input class="form-control" type="time" ng-model="zeile.ende_soll"/></td>
+        <td><input class="form-control" type="date" ng-model="zeile.erster_status"/></td>
+        <td><select class="form-control" ng-model="zeile.woche" ng-options="v for v in domain.woche"></select></td>
+        <td>
+            <div class="input-group">
+                <div class="input-group-addon">{{zeile.bundesland}}</div>
+                <select class="form-control" ng-model="zeile.bundesland" ng-options="k as v for (k,v) in domain.bundesland"></select>
+            </div>
+        </td>
+        <td><input class="form-control" ng-model="zeile.plz"/></td>
+        <td><input class="form-control" ng-model="zeile.ort"/></td>
+        <td>
+            <a ng-href="#/overview/{{zeile.kunde}}/all/all"><button type="button" class="btn btn-default" title="Fehlermeldungen"><span class="glyphicon glyphicon-exclamation-sign"></span></button></a>
+            <a ng-href="#/stats/{{zeile.kunde}}"><button type="button" class="btn btn-default" title="Statistik"><span class="glyphicon glyphicon-stats"></span></button></a>
+            <a ng-href="#/config/{{zeile.kunde}}/current"><button type="button" class="btn btn-default" title="Konfiguration"><span class="glyphicon glyphicon-list-alt"></span></button></a>
+            <a><button type="button" class="btn btn-default" title="Kalender"><span class="glyphicon glyphicon-calendar"></span></button></a>
+        </td>
+    </tr>
+</table>
+</form>
+
+<!-- Modal -->
+<div class="modal fade" id="fehler-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title" id="myModalLabel">Fehlerbericht {{current.kunde}} - {{current.datum}}</h4>
+            </div>
+            <div class="modal-body">
+                <pre>
+                    {{current.fehler.logdatei}}
+                </pre>
+
+                <div class="logdatei" ng-repeat="e in current.fehler.fehlerbericht">
+                    <p class="modell" ng-class="{'rot':e.ErrorLevel < 3}">{{e.Type}}: {{e.Name}}</p>
+                    <p class="dateiname">
+                        Dateiname: {{e.Filename}}<br />
+                        Stand: {{dateFormat(e.Modified)}} ({{e.LastChangedDays}} Tage)
+                    </p>
+
+                    <div ng-show="e.Errors.length > 0">
+
+                        <ul class="fehler" ng-show="e.Type=='Modell'">
+                            <li ng-repeat="error in e.Errors"><a href="http://wiki.global-cube.de/{{error.Number}}">{{error.Number}}</a>:
+                                ({{error.Level}}) {{error.Message}}</li>
+                        </ul>
+                        <ul class="fehler" ng-show="e.Type=='WebCreator'">
+                            <li ng-repeat="error in e.Errors"><a href="http://wiki.global-cube.de/{{error.Number}}">{{error.Number}}</a>:
+                                ({{error.Level}}) {{error.Message}}</li>
+                        </ul>
+                        <table class="ft" ng-show="e.Type=='Portal'||e.Type=='Versand'">
+                            <tbody ng-repeat="error in e.Errors">
+                                <tr>
+                                    <td rowspan="5" class="number">{{$index+1}}
+                                    <td>Datei:</td>
+                                    <td>{{error.Filename}}</td>
+                                </tr>
+                                <tr>
+                                    <td>Stand:</td>
+                                    <td>{{error.Modified}}</td>
+                                </tr>
+                                <tr>
+                                    <td>Benutzer:</td>
+                                    <td>{{error.User}}</td>
+                                </tr>
+                                <tr>
+                                    <td>Bericht:</td>
+                                    <td>{{error.Report}} (Schicht {{error.Layer}})</td>
+                                </tr>
+                                <tr class="strich">
+                                    <td>Empfänger:</td>
+                                    <td>{{error.MailTo}}</td>
+                                </tr>
+                            </tbody>
+                        </table>
+
+                    </div>
+                </div>
+
+
+                <table class="table table-hover table-bordered">
+                    <tr>
+                        <th>Benutzer</th>
+                        <td>
+                            <input type="text" ng-model="current.fehler.benutzer" />
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Kommentar</th>
+                        <td>
+                            <label>
+                                <textarea cols="40" rows="5">{{current.fehler.kommentar}}</textarea>
+                            </label>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Anzahl Fehler</th>
+                        <td>
+                            <label>
+                                <input type="text" ng-model="current.fehler.anzahl"/>
+                            </label>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Bearbeitungsstand</th>
+                        <td>
+                            <label>
+                                <select ng-model="current.fehler.bearbeitet" ng-options="k as v for (k,v) in domain.bearbeitet"></select>
+                            </label>
+                        </td>
+                    </tr>
+                </table>
+
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-primary" ng-click="saveComments()" data-dismiss="modal">Speichern</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+
+
+<style>
+.table tbody tr td {
+    vertical-align: middle;
+}
+
+.label-0 {
+    background-color: #aaaaaa;
+}
+
+.label-1 {
+    background-color: #bbbb00;
+}
+
+.label-2 {
+    background-color: #bb8800;
+}
+
+.label-3 {
+    background-color: #bb0000;
+}
+
+
+table.ft {
+    border: 1px solid #888;
+}
+
+table.ft td {
+    padding: 3px 5px;
+    margin: 2px;
+    background-color: #ddd;
+}
+
+.logdatei {
+    margin: 10px 5px 20px 5px;
+    padding: 0 20px 10px 20px;
+    background-color: #eee;
+    border: 1px solid #888;
+}
+
+.modell {
+    font-weight: bold;
+    background-color: #ccc;
+    padding: 10px;
+    margin: 0 -20px;
+}
+
+.rot {
+    background-color: #e88;
+}
+
+.number {
+    font-weight: bold;
+    background-color: #ccc;
+    border: 1px solid #888888;
+}
+
+.strich {
+    border-bottom: 1px solid #888888;
+}
+
+</style>

+ 260 - 109
app/views/overview.html

@@ -1,112 +1,252 @@
-<button type="button" class="btn btn-info" ng-click="importData()">
-    <span class="glyphicon glyphicon-refresh"></span>
-</button>
-<br/><br/>
-<div class="alert alert-success" role="alert" ng-show="error > -1" ng-class="{'alert-danger': error == 1}">
-    Neu importiert:
-    <ul>
-        <li ng-repeat="opt in info">{{opt}}</li>
+<div class="container-fluid">
+    <div class="well" ng-show="benutzer==null">
+        Benutzer:<br/>
+        <div class="dropdown">
+            <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{benutzer2||'unbekannt'}}&nbsp;<b class="caret"></b></a>
+            <ul class="dropdown-menu" role="menu">
+                <li ng-repeat="val in domain.benutzer"><a ng-click="benutzer2=val">{{val}}</a></li>
+            </ul>
+        </div>
+        <br/>
+
+        <button class="btn btn-default btn-sm" ng-click="saveUser(benutzer2)">Speichern</button>
+    </div>
+
+    <ul class="nav nav-pills">
+        <li><a ng-href="#/overview/all/today/errors">Heutige Fehler</a></li>
+        <li><a ng-href="#/overview/all/today/all">Heutige Statusmeldungen</a></li>
+        <li><a ng-href="#/overview/all/all/missing">Alle Fehlenden</a></li>
+        <li><a ng-href="#/overview/all/all/errors">Alle Fehler</a></li>
     </ul>
-</div>
 
-<div class="well" ng-show="benutzer==null">
-    <label>Benutzer:
-        <input ng-model="benutzer2"/>
-    </label>
-    <button class="btn btn-default btn-sm" ng-click="saveUser(benutzer2)">Speichern</button>
 </div>
 
+<div class="row">
+    <div class="container-fluid col-md-7">
 <table class="table table-bordered table-striped">
     <tr>
-        <th>Datum</th>
-        <th>Kunde</th>
-        <th>Start</th>
-        <th>Ende (Soll/Ist)</th>
+        <th>
+            <label>
+                Datum <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='datum'"></i><br/>
+                <input ng-model="Filter.datum" type="date" ng-change="refresh()" />
+            </label>
+        </th>
+        <th>
+            <label>
+                Kunde <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='kunde'"></i><br/>
+                <input ng-model="Filter.kunde" />
+            </label>
+        </th>
+        <th>Start Soll<br/>Ende Soll <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='ende_soll'"></i></th>
+        <th>Start Ist<br/>Ende Ist</th>
         <th>Abweichung</th>
-        <th>Fehler</th>
+        <th>Fehler / Statistik</th>
+        <th>Kommentar</th>
     </tr>
     <tr>
+        <td>
+        </td>
         <td>
             <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{dateFormat(Filter.datum)||'alle'}}&nbsp;<b class="caret"></b></a>
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.system||'alle'}}&nbsp;<b class="caret"></b></a>
                 <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.datum=''">alle</a></li>
+                    <li><a ng-click="Filter.system=''">alle</a></li>
                     <li class="divider"></li>
-                    <li ng-repeat="opt in datum"><a ng-click="Filter.datum=opt">{{dateFormat(opt)}}</a></li>
+                    <li ng-repeat="val in domain.system"><a ng-click="Filter.system=val">{{val}}</a></li>
                 </ul>
             </div>
         </td>
+        <td></td>
         <td>
             <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.kunde||'alle'}}&nbsp;<b class="caret"></b></a>
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.fehlend[Filter.fehlend]||'alle'}}&nbsp;<b class="caret"></b></a>
                 <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.kunde=''">alle</a></li>
+                    <li><a ng-click="Filter.fehlend=''">alle</a></li>
                     <li class="divider"></li>
-                    <li ng-repeat="opt in kunden"><a ng-click="Filter.kunde=opt.kunde">{{opt.kunde}}</a></li>
+                    <li ng-repeat="(key,val) in domain.fehlend"><a ng-click="Filter.fehlend=key">{{val}}</a></li>
                 </ul>
             </div>
         </td>
         <td></td>
-        <td></td>
-        <td></td>
         <td>
             <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">fehlerhafte&nbsp;<b class="caret"></b></a>
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.fehler[Filter.fehler]||'alle'}}&nbsp;<b class="caret"></b></a>
                 <ul class="dropdown-menu" role="menu">
                     <li><a ng-click="Filter.fehler=''">alle</a></li>
                     <li class="divider"></li>
-                    <li><a ng-click="Filter.fehler='1'">fehlerhafte</a></li>
-                    <li><a ng-click="Filter.fehler='0'">fehlerfreie</a></li>
+                    <li ng-repeat="(key,val) in domain.fehler"><a ng-click="Filter.fehler=key">{{val}}</a></li>
+                </ul>
+            </div>
+        </td>
+        <td>
+            <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.benutzer||'alle'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                    <li><a ng-click="Filter.benutzer=''">alle</a></li>
+                    <li class="divider"></li>
+                    <li ng-repeat="val in domain.benutzer"><a ng-click="Filter.benutzer=val">{{val}}</a></li>
                 </ul>
             </div>
         </td>
     </tr>
 
-    <tr ng-repeat="zeile in overview | filter:Filter" ng-class="{'danger':zeile.kommentar==null}">
+    <tr ng-repeat="zeile in overview | filter:SearchText | filter:Filter | orderBy:Predicate:Reverse" ng-class="{'danger':zeile.fehlend==1}">
         <td>{{dateFormat(zeile.datum)}}</td>
-        <td><span class="label label-danger label-{{zeile.system}}">{{zeile.system}}</span> {{zeile.kunde}}</td>
-        <td>{{zeile.start_soll}}<br/>{{zeile.start}}</td>
-        <td>{{zeile.ende_soll}}<br/>{{zeile.ende}}</td>
-        <td>{{minuten(zeile.abweichung)}}</td>
-        <td><a data-toggle="modal" data-target="#fehler-modal" ng-click="setCurrent(zeile)"><span class="label label-danger label-{{zeile.anzahl}}">{{zeile.anzahl}}</span></a>
-            <button type="button" class="btn btn-default btn-sm" ng-show="zeile.bearbeitet != '0'" data-toggle="tooltip" data-placement="top" title="{{zeile.kommentar}}">
-                <span class="glyphicon" ng-class="{'glyphicon-ok':zeile.kommentar=='', 'glyphicon-comment':zeile.kommentar!=''&&zeile.kommentar!=null, 'glyphicon-question-sign':zeile.kommentar==null}"></span> {{zeile.benutzer}}
+        <td><span class="label label-danger label-{{zeile.system}}">{{left(zeile.system, 1)}}</span> <a ng-href="#/overview/{{zeile.kunde}}/all/all">{{zeile.kunde}}</a></td>
+        <td>{{zeile.start_soll}}<br/>{{zeile.ende_soll}}</td>
+        <td>
+            <a ng-click="saveStartTime(zeile)">{{zeile.start}}</a><br/>
+            <a ng-click="saveEndTime(zeile)">{{zeile.ende}}</a>
+        </td>
+        <td>
+            {{timeDiffStart(zeile)}}<br/>
+            {{timeDiff(zeile)}}</td>
+        <td>
+            <button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#stats-modal" ng-click="setCurrent(zeile)" ng-show="zeile.anzahl != null">
+                <span class="glyphicon glyphicon-stats"></span>
+            </button>
+            <!--<a ng-href="#/overview/{{zeile.kunde}}/all/all"><button type="button" class="btn btn-default" title="Fehlermeldungen"><span class="glyphicon glyphicon-exclamation-sign"></span></button></a>-->
+            <!--<a ng-href="#/stats/{{zeile.kunde}}"><button type="button" class="btn btn-default" title="Statistik"><span class="glyphicon glyphicon-stats"></span></button></a>-->
+
+            <!--<a ng-href="#/config/{{zeile.kunde}}/current"><button type="button" class="btn btn-default" title="Konfiguration"><span class="glyphicon glyphicon-list-alt"></span></button></a>-->
+
+            <button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#fehler-modal" ng-click="setCurrent(zeile)" ng-show="zeile.anzahl != null">
+                <span class="glyphicon" ng-class="{'glyphicon-check': zeile.anzahl == 0 && zeile.bearbeitet == 1, 'glyphicon-eye-close': zeile.anzahl == 0 && zeile.bearbeitet == 0,  'glyphicon-exclamation-sign': zeile.anzahl > 0 && zeile.bearbeitet == 0,  'glyphicon-ok': zeile.anzahl > 0 && zeile.bearbeitet == 1}"></span>
+                <span class="label label-danger label-{{zeile.anzahl}}"> {{zeile.anzahl}}</span>
+            </button>
+
+            <button type="button" data-trigger="focus" class="btn btn-default btn-sm" data-toggle="modal" data-target="#fehler-modal" ng-click="setCurrent(zeile)" ng-show="zeile.anzahl == null">
+                <span class="glyphicon glyphicon-question-sign"></span>
+            </button>
+        </td>
+        <td>
+            <button type="button" class="btn btn-default btn-sm" ng-init="c = getComments(zeile)" ng-show="c" data-toggle="popover" data-placement="bottom" title="test" data-content="{{c[0].kommentar}}
+{{domain.bearbeitet[c[0].status]}}">
+                <span ng-show="c[0].datum != zeile.datum">{{dateFormat(c[0].datum)}}: </span>
+                <span class="glyphicon {{getCommentIcon(c)}}"></span>
+                <span class="label label-danger label-{{c[0].fehler}}"> {{c[0].fehler}}</span>
+                {{c[0].benutzer}}
             </button>
         </td>
     </tr>
 </table>
-
+    </div>
+</div>
 
 <!-- Modal -->
-<div class="modal fade" id="fehler-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-    <div class="modal-dialog">
+<div class="modal fade" id="fehler-modal" tabindex="-1" role="dialog" aria-labelledby="fehler-modal-label" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
         <div class="modal-content">
             <div class="modal-header">
                 <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-                <h4 class="modal-title" id="myModalLabel">Fehlerbericht {{current.kunde}} - {{current.datum}}</h4>
+                <h4 class="modal-title" id="fehler-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp; {{current.zeile.kunde}} - {{dateFormat(current.zeile.datum)}}</h4>
             </div>
+
+
             <div class="modal-body">
-                <pre>
-                    {{current.fehler.logdatei}}
-                </pre>
 
-                <div class="logdatei" ng-repeat="e in current.fehler.fehlerbericht">
-                    <p class="modell" ng-class="{'rot':e.Errors.length > 0}">{{e.Type}}: {{e.Name}}</p>
-                    <p class="dateiname">
-                        Dateiname: {{e.Filename}}<br />
-                        Stand: {{dateFormat(e.Modified)}} ({{e.LastChangedDays}} Tage)
-                    </p>
+                <table class="table table-hover table-bordered">
+                    <tr>
+                        <td>
+                            <button class="btn btn-default" ng-click="current.kommentar=current.template"><span class="glyphicon glyphicon-plus"></span></button>
+                        </td>
+                        <th style="width: 130px;">Datum</th>
+                        <th style="width: 100px;">Benutzer</th>
+                        <th style="width: 170px;">Status</th>
+                        <th style="width: 70px;">Anzahl</th>
+                        <th style="width: 340px;">Kommentar</th>
+                    </tr>
+                    <tr>
+                        <td></td>
+                        <td></td>
+                        <td></td>
+                        <td>
+                            <div class="dropdown">
+                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.statusfilter[current.status]||'alle'}}&nbsp;<b class="caret"></b></a>
+                                <ul class="dropdown-menu" role="menu">
+                                    <li><a ng-click="current.status=''">alle</a></li>
+                                    <li class="divider"></li>
+                                    <li ng-repeat="(key,val) in domain.statusfilter"><a ng-click="current.status=key">{{val}}</a></li>
+                                </ul>
+                            </div>
+                        </td>
+                        <td></td>
+                        <td></td>
+                    </tr>
+                    <tr ng-repeat="c in comments[current.zeile.kunde] | filter:statusFilter | orderBy: 'datum' ">
+                        <td><button class="btn btn-default" ng-click="current.kommentar=c;c.fehler=parseInt(c.fehler,10)"><span class="glyphicon glyphicon-pencil"></span></button></td>
+                        <td>{{dateFormat(c.datum)}}</td>
+                        <td>{{c.benutzer}}</td>
+                        <td><span class="glyphicon {{getCommentIcon(c)}}"></span> {{domain.bearbeitet[c.status]}}</td>
+                        <td><span class="label label-danger label-{{c.fehler}}"> {{c.fehler}}</span></td>
+                        <td>{{c.kommentar}}</td>
+                    </tr>
+                </table>
+
+                <table class="table table-hover table-bordered">
+                    <tr>
+                        <th>Benutzer</th>
+                        <td>
+                            <div class="dropdown">
+                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{current.kommentar.benutzer||'unbekannt'}}&nbsp;<b class="caret"></b></a>
+                                <ul class="dropdown-menu" role="menu">
+                                    <li ng-repeat="val in domain.benutzer"><a ng-click="current.kommentar.benutzer=val">{{val}}</a></li>
+                                </ul>
+                            </div>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Bearbeitungsstand</th>
+                        <td>
+                            <div class="dropdown">
+                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown"><span class="glyphicon {{getCommentIcon(current.kommentar)}}"></span> {{domain.bearbeitet[current.kommentar.status]||'unbekannt'}}&nbsp;<b class="caret"></b></a>
+                                <ul class="dropdown-menu" role="menu">
+                                    <li ng-repeat="(key,val) in domain.bearbeitet"><a ng-click="current.kommentar.status=key"><span class="glyphicon {{domain.comment[key]}}"></span> {{val}}</a></li>
+                                </ul>
+                            </div>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Anzahl Fehler
+                            <span class="label label-danger label-{{current.fehler.anzahl}}"> {{current.fehler.anzahl}}</span>
+                        </th>
+                        <td>
+                            <span class="label label-danger label-{{current.kommentar.fehler}}"> {{current.kommentar.fehler}}</span> &nbsp;
+                            <label>
+                                <input type="range" name="Anzahl" min="0" max="10" ng-model="current.kommentar.fehler" />
+                            </label>
+                        </td>
+                    </tr>
+                    <tr>
+                        <th>Kommentar</th>
+                        <td>
+                            <label>
+                                <textarea cols="60" rows="5" ng-model="current.kommentar.kommentar"></textarea>
+                            </label>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td></td>
+                        <td>
+                            <button type="button" class="btn btn-default" ng-click="saveComments()">Speichern</button>
+                            <button type="button" class="btn btn-primary" ng-click="saveComments()" data-dismiss="modal">Speichern und schließen</button>
+                        </td>
+                    </tr>
+                </table>
 
-                    <div ng-show="e.Errors.length > 0">
 
+                <div class="logdatei" ng-repeat="e in current.fehler.fehlerbericht | filter: errorLevel | orderBy: 'ErrorLevel'">
+                    <a href="" onclick="$(this).next().toggle()">
+                        <p class="modell" ng-class="{'rot':e.ErrorLevel < 3}">{{e.Type}}: {{e.Name}} ({{errorCount(e)}})</p>
+                    </a>
+
+
+                    <div class="closed-tab">
                         <ul class="fehler" ng-show="e.Type=='Modell'">
                             <li ng-repeat="error in e.Errors"><a href="http://wiki.global-cube.de/{{error.Number}}">{{error.Number}}</a>:
                                 ({{error.Level}}) {{error.Message}}</li>
                         </ul>
-                        <ul class="fehler" ng-show="e.Type=='WebCreator'">
-                            <li ng-repeat="error in e.Errors"><a href="http://wiki.global-cube.de/{{error.Number}}">{{error.Number}}</a>:
-                                ({{error.Level}}) {{error.Message}}</li>
-                        </ul>
+                        <pre class="fehler" ng-show="e.Type=='Workflow'">{{e.Errors[0]}}</pre>
                         <table class="ft" ng-show="e.Type=='Portal'||e.Type=='Versand'">
                             <tbody ng-repeat="error in e.Errors">
                                 <tr>
@@ -128,7 +268,7 @@
                                 </tr>
                                 <tr class="strich">
                                     <td>Empfänger:</td>
-                                    <td>{{error.MailTo}}</td>
+                                    <td><div ng-bind-html="mailFormat(error.MailTo)"></div></td>
                                 </tr>
                             </tbody>
                         </table>
@@ -138,47 +278,82 @@
 
 
                 <table class="table table-hover table-bordered">
-                    <tr>
-                        <th>Benutzer</th>
-                        <td>
-                            <input type="text" ng-model="current.fehler.benutzer" />
-                        </td>
-                    </tr>
-                    <tr>
-                        <th>Kommentar</th>
+                    <tr ng-repeat="(header, g) in current.fehler.weitere">
+                        <th>{{header}}</th>
+
                         <td>
-                            <label>
-                                <textarea cols="40" rows="5">{{current.fehler.kommentar}}</textarea>
-                            </label>
+                            <ul>
+                                <li ng-repeat="e in g">
+                                    {{e.Name}}
+                                </li>
+                            </ul>
                         </td>
                     </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+</div>
+
+<div class="modal fade" id="stats-modal" tabindex="-1" role="dialog" aria-labelledby="stats-modal-label" aria-hidden="true">
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+                <h4 class="modal-title" id="stats-modal-label"><span class="glyphicon glyphicon-stats"></span>&nbsp; {{current.zeile.kunde}} - {{dateFormat(current.zeile.datum)}}</h4>
+            </div>
+            <div class="modal-body">
+                <div id="duration" style="width: 750px; height: 550px">
+
+                </div>
+                <br/><br/>
+                <table class="table table-bordered table-striped">
                     <tr>
-                        <th>Anzahl Fehler</th>
-                        <td>
-                            <label>
-                                <input type="text" ng-model="current.fehler.anzahl"/>
-                            </label>
-                        </td>
+                        <th>Name</th>
+                        <th>Datum</th>
+                        <th>Zeit</th>
+                        <th>Dauer</th>
+                        <th>Quellen</th>
+                        <th>Kategorien</th>
+                        <th>Datensätze</th>
                     </tr>
-                    <tr>
-                        <th>Bearbeitungsstand</th>
-                        <td>
-                            <label>
-                                <select ng-model="current.fehler.bearbeitet" ng-options=""></select>
-                            </label>
-                        </td>
+                    <tr ng-repeat="e in current.fehler.fehlerbericht" ng-show="e.Summary.Duration != null">
+                        <td>{{e.Type}}: <a href="" ng-click="showDetails(e)">{{e.Name}}</a></td>
+                        <td>{{dateFormat(e.Modified)}}</td>
+                        <td>{{timeFormat(e.Modified)}}</td>
+                        <td>{{e.Summary.Duration}}</td>
+                        <td>{{e.Sources.length}}</td>
+                        <td>{{e.Summary.Categories}}</td>
+                        <td>{{e.Summary.Entities}}</td>
                     </tr>
                 </table>
 
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-primary" ng-click="saveComments()">Speichern</button>
+                <div ng-show="current.details!=null">
+                    <h3>Details zu {{current.details.Type}}: {{current.details.Name}}</h3>
+                    <div id="duration_details" style="width: 750px; height: 550px">
+
+                    </div>
+                    <br/><br/>
+                    <table class="table table-bordered table-striped">
+                        <tr>
+                            <th>Name</th>
+                            <th ng-show="current.details.Type!='Modell'">Report</th>
+                            <th ng-show="current.details.Type=='Modell'">Datensätze</th>
+                            <th>Dauer</th>
+                        </tr>
+                        <tr ng-repeat="e in current.details.Sources">
+                            <td>{{e.Filename}}</td>
+                            <td ng-show="current.details.Type!='Modell'">{{e.Report}} ({{e.Layer}})</td>
+                            <td ng-show="current.details.Type=='Modell'">{{e.Entities}}</td>
+                            <td>{{e.Duration}}</td>
+                        </tr>
+                    </table>
+                </div>
             </div>
         </div>
     </div>
 </div>
 
-
 <style>
 .table tbody tr td {
     vertical-align: middle;
@@ -200,30 +375,6 @@
     background-color: #bb0000;
 }
 
-.label-O {
-    background-color: #888888;
-}
-
-.label-E {
-    background-color: #338833;
-}
-
-.label-G {
-    background-color: #5577cc;
-}
-
-.label-B {
-    background-color: #0022bb;
-}
-
-.label-A {
-    background-color: #dddd22;
-    color: #000000;
-}
-
-
-
-
 table.ft {
     border: 1px solid #888;
 }

+ 20 - 0
app/views/stats.html

@@ -0,0 +1,20 @@
+<label>Kunde:
+    <select class="form-control" ng-model="customer" ng-options="k for k in options.customer" ng-change="refresh()"></select>
+</label>
+
+<div class="row">
+    <div class="container-fluid col-md-6">
+        <table class="table table-bordered table-striped">
+            <tr>
+                <th></th>
+                <th>Anzahl</th>
+                <th>Details</th>
+            </tr>
+            <tr ng-repeat="(key,val) in summary">
+                <th>{{key}}</th>
+                <td>{{val.length}}</td>
+                <td><ul><li ng-repeat="v in val" ng-class="{'red':test(v)}">{{v}}</li></ul></td>
+            </tr>
+        </table>
+    </div>
+</div>

+ 2 - 0
bower.json

@@ -13,6 +13,8 @@
         "angular-touch": "1.2.16",
         "angular-route": "1.2.16",
         "angular-bootstrap": "~0.11.0",
+        "flot": "~0.8.3",
+        "fullcalendar": "~2.1.1",
         "moment": "~2.8.3",
         "underscore": "~1.6.0"
     },