diff --git a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
index 741ab92a4d39bc694a37e0ce0b913accdd1cc265..49f6fdde84face75fc6e053c5814c36cd955c6b0 100644
--- a/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/Attribute_entity/recordcontainers/jdito/contentProcess.js
@@ -127,20 +127,30 @@ attributes.forEach(function ([attributeId, parentId, simpleName, isActive,
     ]);
 });
 
+var sorter = new AttributeSorter(vars.get("$local.order"));
+
 var resultTable = [];
 do {
     var oldSize = resultTable.length;
+    var layer = [];
     attributesById.forEach(function (row, id)
     {   
-        var parentId = row[3];
+        if (!row)
+        {
+            attributesById["delete"](id);
+            return;
+        }
+        var parentId = row[4];
         //rows that are already in the result array are removed from the attributesById Map, so if the parentId is in that Map,
         //the parent has not been added yet
         if (!parentId || !attributesById.has(parentId))
         {
-            resultTable.push(row);
-            attributesById["delete"](id);
+            layer.push(row);
+            attributesById.set(id, null);
         }
     });
+    sorter.sort(layer);
+    resultTable = resultTable.concat(layer);
 } while (oldSize != resultTable.length); //stops the loop when no new items were added so that recursive relations between attributes don't cause an infinite loop
 
 result.object(resultTable);
@@ -217,4 +227,42 @@ function AttributeUsageLoader ()
             return ContextUtils.getTitle(usage, true);
         }).join(", ");
     }
+}
+
+function AttributeSorter (pSortOrder)
+{
+    if (Utils.isNullOrEmpty(pSortOrder))
+    {
+        this.sort = function (pArray) {return pArray;};
+    }
+    else
+    {
+        var fieldIndexes = {
+            "ATTRIBUTE_NAME.value": 1,
+            "TRANSLATED_NAME.value": 2,
+            "ATTRIBUTE_TYPE.displayValue": 7,
+            "ATTRIBUTE_ACTIVE.value": 8,
+            "SORTING.value": 9,
+            "USAGELIST.value": 13
+        };
+        var sortOrder = Utils.objectEntries(vars.get("$local.order"));
+        if (sortOrder.length === 0)
+        {
+            sortOrder = [["ATTRIBUTE_NAME.value", "UP"]]
+        }
+        sortOrder = Utils.objectEntries(vars.get("$local.order")).reduce(function (orderMap, [field, direction])
+        {
+            if (field in fieldIndexes)
+            {
+                orderMap.set(fieldIndexes[field], direction == "DOWN");
+            }
+            return orderMap;
+        }, new Map());
+        var sortFn = ArrayUtils.getMultiSortCompareFn(sortOrder);
+        
+        this.sort = function (pArray)
+        {
+            return pArray.sort(sortFn);
+        }
+    }
 }
\ No newline at end of file
diff --git a/neonContext/WorkflowStartConfig/WorkflowStartConfig.aod b/neonContext/WorkflowStartConfig/WorkflowStartConfig.aod
index 5261c781f8746359414b7c3c92f5783050136ff7..7915d25a13f55ec7d8af1a37fad65f7a279ac588 100644
--- a/neonContext/WorkflowStartConfig/WorkflowStartConfig.aod
+++ b/neonContext/WorkflowStartConfig/WorkflowStartConfig.aod
@@ -2,11 +2,17 @@
 <neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1">
   <name>WorkflowStartConfig</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterView>WorkflowStartConfigFilter_view</filterView>
+  <editView>WorkflowStartConfigEdit_view</editView>
   <entity>WorkflowStartConfig_entity</entity>
   <references>
     <neonViewReference>
       <name>c6e5379e-3df6-4f1d-be39-32fd1ad0852d</name>
       <view>WorkflowStartConfigFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>a8c1e94d-83cb-45c3-afc3-70686705ab82</name>
+      <view>WorkflowStartConfigEdit_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonView/WorkflowStartConfigEdit_view/WorkflowStartConfigEdit_view.aod b/neonView/WorkflowStartConfigEdit_view/WorkflowStartConfigEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..90a5234ad36788b21d38e28fc9b9708192a91597
--- /dev/null
+++ b/neonView/WorkflowStartConfigEdit_view/WorkflowStartConfigEdit_view.aod
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8">
+  <name>WorkflowStartConfigEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <size>SMALL</size>
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <genericViewTemplate>
+      <name>StartConfig</name>
+      <editMode v="true" />
+      <fields>
+        <entityFieldLink>
+          <name>48b1dd11-5964-4d46-85eb-3f144ab7b3d2</name>
+          <entityField>OBJECT_TYPE</entityField>
+        </entityFieldLink>
+      </fields>
+    </genericViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/WorkflowStartConfigFilter_view/WorkflowStartConfigFilter_view.aod b/neonView/WorkflowStartConfigFilter_view/WorkflowStartConfigFilter_view.aod
index 2ced9ab248fdce98ea9019cc4442571c4c8c811e..ddee9e3a21a1d14c749fdd5c0a2a2c8644b0ae1b 100644
--- a/neonView/WorkflowStartConfigFilter_view/WorkflowStartConfigFilter_view.aod
+++ b/neonView/WorkflowStartConfigFilter_view/WorkflowStartConfigFilter_view.aod
@@ -10,8 +10,6 @@
   <children>
     <tableViewTemplate>
       <name>Table</name>
-      <inlineEdit v="true" />
-      <autoNewRow v="true" />
       <entityField>#ENTITY</entityField>
       <columns>
         <neonTableColumn>
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index 2a72f327942d4adb6a0472566e15163f23a90256..ecc8f1ed818c8617735dd702a025269dfcfd8fdf 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -1882,7 +1882,9 @@ SqlBuilder.prototype.build = function(pDefaultConditionIfNone)
  * @param {String[]} pColumns The columns where you want to update.
  * @param {SQLTYPES[]} [pColumnTypes=null] normally you can set this to null as the types are calculated if not provided
  * @param {String[]} pValues The values to be updated.
- * @param {Number} [pTimeout=-1] 
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {Number} the number of rows affected
  * @throws {Error} if no table is defined
  */
@@ -2008,7 +2010,9 @@ SqlBuilder.prototype.buildInsertStatement = function (pFieldValues, pTableName,
  * @param {String[]} pColumns The columns where you want to insert into.
  * @param {SQLTYPES[]} [pColumnTypes=null] normally you can set this to null as the types are calculated if not provided
  * @param {String[]} pValues The values to be inserted.
- * @param {Number} [pTimeout=-1] 
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {Number} the number of rows affected
  * @throws {Error} if no table is defined
  */
@@ -2106,7 +2110,9 @@ SqlBuilder._columnsValuesFromObject = function (pFieldValues, pIncludeNullValues
  *      <strong>IMPORTANT: If this is set to false and there is no condition, every row in the table will be deleted!</strong>
  * @param {String} [pTableName] The table for deleting data. If undefined, the from part of the SqlBuilder will be used. If no from is set,
  *      the table of the first where-condition is used.
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {Number} the number of rows affected
  * @throws {Error} if no table is defined
  * @example 
@@ -2189,8 +2195,12 @@ SqlBuilder.prototype.cell = function(pExecuteOnlyIfConditionExists, pFallbackVal
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pMaxRows=0]
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+   *                If you do not want to restrict this value, enter 0.
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[]} the result of the query
  */
 SqlBuilder.prototype.arrayRow = function (pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
@@ -2203,8 +2213,12 @@ SqlBuilder.prototype.arrayRow = function (pExecuteOnlyIfConditionExists, pMaxRow
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pMaxRows=0]
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+   *                If you do not want to restrict this value, enter 0.
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[]} the result of the query
  */
 SqlBuilder.prototype.arrayColumn = function (pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
@@ -2218,8 +2232,12 @@ SqlBuilder.prototype.arrayColumn = function (pExecuteOnlyIfConditionExists, pMax
  * 
  * @param {Number} pType db.ROW or db.COLUMN
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pMaxRows=0]
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+   *                If you do not want to restrict this value, enter 0.
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[]} the result of the query
  */
 SqlBuilder.prototype.array = function(pType, pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
@@ -2245,7 +2263,9 @@ SqlBuilder.prototype.array = function(pType, pExecuteOnlyIfConditionExists, pMax
  * @param {Number} pStartIndex
  * @param {Number} pRowCount
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[]} the result of the query
  */
 SqlBuilder.prototype.arrayPage = function(pType, pStartIndex, pRowCount, pExecuteOnlyIfConditionExists, pTimeout)
@@ -2269,8 +2289,12 @@ SqlBuilder.prototype.arrayPage = function(pType, pStartIndex, pRowCount, pExecut
  * Note: the default for pExecuteOnlyIfConditionExists is false becausse it is more natural to select all rows if no condition exists.
  * 
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pMaxRows=0]
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pMaxRows=0] The maximum number of rows to be returned (ORDER BY must be defined in the SQL statement!).
+   *                If you specify maxRows, this restriction might apply to all tables indicated in the JOIN part of the query.
+   *                If you do not want to restrict this value, enter 0.
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[][]} the result of the query
  */
 SqlBuilder.prototype.table = function(pExecuteOnlyIfConditionExists, pMaxRows, pTimeout)
@@ -2295,7 +2319,9 @@ SqlBuilder.prototype.table = function(pExecuteOnlyIfConditionExists, pMaxRows, p
  * @param {Number} pStartIndex
  * @param {Number} pRowCount
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[][]} the result of the query
  */
 SqlBuilder.prototype.tablePage = function(pStartIndex, pRowCount, pExecuteOnlyIfConditionExists, pTimeout)
@@ -2343,7 +2369,9 @@ SqlBuilder.prototype.startRow = function (pStartRow)
  * for iterating over the table pages. You can use SqlBuilder.prototype.hasMoreRows() to check if the end of rows was reached.
  * 
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  * @return {String[][]} the result of the query
  */
 SqlBuilder.prototype.nextTablePage = function (pExecuteOnlyIfConditionExists, pTimeout)
@@ -2383,7 +2411,9 @@ SqlBuilder.prototype.hasMoreRows = function ()
  * 
  * @param {Function} pCallBackFn CallBack-Function to execute for every page. If the function returns false, the execution will be stopped.
  * @param {Boolean} [pExecuteOnlyIfConditionExists=false] if true and there is no condition, [] is returned
- * @param {Number} [pTimeout=-1]
+ * @param {Number} [pTimeout=-1] Specifies the period, in milliseconds, after which the query will be aborted.
+ *                  This timeout value overwrites DBSyncTimeout for the SQL command to be executed (this value was predefined in the
+ *                  server defaults). If you omit this parameter, DBSyncTimeout will be used.
  */
 SqlBuilder.prototype.forEachPage = function (pCallBackFn, pExecuteOnlyIfConditionExists, pTimeout)
 {
diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js
index ada0e3f465462c2959c61f639b5dc3d379cb38e1..5baa6ba7c6517bb00640530ffbcd085e759eaaa0 100644
--- a/process/Util_lib/process.js
+++ b/process/Util_lib/process.js
@@ -981,23 +981,51 @@ ArrayUtils.sortArrayOfObjects = function(targetArray, key, sortAsc, isNumber) {
 /**
 * sorts an array with columns
 *
-* @param {Array} targetArray the array with data
-* @param {Array} sortOrder array with the format [columnIndex1, sortDescending1, columnIndex2, sortDescending2, ...],
+* @param {Array} pTargetArray the array with data
+* @param {Array} pSortOrder array with the format [columnIndex1, sortDescending1, columnIndex2, sortDescending2, ...],
 *                           the columnIndex must be an integer, sortDescending must be boolean (true -> descending, just like db.DESCENDING)
 * @example
 * ArrayUtils.sortMulti(rows, [1, true, 2, true, 5, false]);
 *
 * @return {void}
 */
-ArrayUtils.sortMulti = function(targetArray, sortOrder) {
+ArrayUtils.sortMulti = function(pTargetArray, pSortOrder) 
+{
+    var sortFn = ArrayUtils.getMultiSortCompareFn(ArrayUtils.chunk(pSortOrder, 2));
+
+    pTargetArray.sort(sortFn);
+    return pTargetArray;
+}
+
+/**
+* makes a sorting function for an array with columns
+*
+* @param {Map|Array} pSortOrder Map with columnIndex as keys and direction as values, or
+*                           array with the format [[columnIndex1, direction1], [columnIndex2, direction2], ...],
+*                           the columnIndex must be an integer, direction must be boolean (true -> descending, just like db.DESCENDING)
+* @example
+* var sortFn = ArrayUtils.getMultiSortCompareFn([[1, true], [2, true], [5, false]]);
+* rows.sort(sortFn);
+*
+* @return {void}
+*/
+ArrayUtils.getMultiSortCompareFn = function (pSortOrder)
+{
+    if (Array.isArray(pSortOrder))
+    {
+        pSortOrder = new Map(pSortOrder);
+    }
+    
     /*
      * @param {String} a req value 1, first compared element
      * @param {String} b req value 2, sencond compared element
      *
      * @return {Integer} -1 - set a below b, 0 - equal, 1 - set b below a 
      */
-    var sortFn = function(a, b) {
-        var stringComparison = function(a, b) {
+    return function(a, b) 
+    {
+        var stringComparison = function(a, b) 
+        {
             a = a.toLowerCase();
             a = a.replace(/ä/g,"ae");
             a = a.replace(/ö/g,"oe");
@@ -1015,28 +1043,31 @@ ArrayUtils.sortMulti = function(targetArray, sortOrder) {
         
         var swap = 0;
         
-        for (let i = 0, l = sortOrder.length; i < l; i += 2)
+        pSortOrder.forEach(function (sortDesc, colIndex)
         {
-            let colIndex = sortOrder[i];
-            let sortDesc = sortOrder[i+1];
             if (swap || colIndex == undefined || sortDesc == undefined)
-                return swap;
+                return;
             
             if (isNaN(a[colIndex] - b[colIndex]))
+            {
                 if ((isNaN(a[colIndex])) && (isNaN(b[colIndex])))
-                    swap =  stringComparison(a[colIndex], b[colIndex]);
+                {
+                    swap = stringComparison(a[colIndex], b[colIndex]);
+                }
                 else
+                {
                     swap = (isNaN(a[colIndex]) ? 1 : -1);
+                }
+            }
             else
+            {
                 swap = (a[colIndex] - b[colIndex]);
+            }    
             
             swap *= (sortDesc ? -1 : 1);
-        }
+        });
         return swap;
     }
-
-    targetArray.sort(sortFn);
-    return targetArray;
 }
 
 /**