mirror of
https://github.com/grocy/grocy.git
synced 2025-08-13 09:17:26 +00:00
Started working on user-defined-fields for all entities (references #176)
This commit is contained in:
@@ -4,6 +4,7 @@ namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\BatteriesService;
|
||||
use \Grocy\Services\UsersService;
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class BatteriesController extends BaseController
|
||||
{
|
||||
@@ -11,9 +12,11 @@ class BatteriesController extends BaseController
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->BatteriesService = new BatteriesService();
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $BatteriesService;
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
@@ -23,7 +26,9 @@ class BatteriesController extends BaseController
|
||||
return $this->AppContainer->view->render($response, 'batteriesoverview', [
|
||||
'batteries' => $this->Database->batteries()->orderBy('name'),
|
||||
'current' => $this->BatteriesService->GetCurrent(),
|
||||
'nextXDays' => $nextXDays
|
||||
'nextXDays' => $nextXDays,
|
||||
'userfields' => $this->UserfieldsService->GetFields('batteries'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('batteries')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -37,7 +42,9 @@ class BatteriesController extends BaseController
|
||||
public function BatteriesList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteries', [
|
||||
'batteries' => $this->Database->batteries()->orderBy('name')
|
||||
'batteries' => $this->Database->batteries()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('batteries'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('batteries')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -46,14 +53,16 @@ class BatteriesController extends BaseController
|
||||
if ($args['batteryId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteryform', [
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('batteries')
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'batteryform', [
|
||||
'battery' => $this->Database->batteries($args['batteryId']),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('batteries')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\ChoresService;
|
||||
use \Grocy\Services\UsersService;
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class ChoresController extends BaseController
|
||||
{
|
||||
@@ -11,9 +12,11 @@ class ChoresController extends BaseController
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->ChoresService = new ChoresService();
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $ChoresService;
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
@@ -23,7 +26,9 @@ class ChoresController extends BaseController
|
||||
return $this->AppContainer->view->render($response, 'choresoverview', [
|
||||
'chores' => $this->Database->chores()->orderBy('name'),
|
||||
'currentChores' => $this->ChoresService->GetCurrent(),
|
||||
'nextXDays' => $nextXDays
|
||||
'nextXDays' => $nextXDays,
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('chores')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -38,7 +43,9 @@ class ChoresController extends BaseController
|
||||
public function ChoresList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'chores', [
|
||||
'chores' => $this->Database->chores()->orderBy('name')
|
||||
'chores' => $this->Database->chores()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('chores')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -57,7 +64,8 @@ class ChoresController extends BaseController
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'choreform', [
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService'),
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores')
|
||||
]);
|
||||
}
|
||||
else
|
||||
@@ -65,7 +73,8 @@ class ChoresController extends BaseController
|
||||
return $this->AppContainer->view->render($response, 'choreform', [
|
||||
'chore' => $this->Database->chores($args['choreId']),
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService'),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,18 @@
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class GenericEntityApiController extends BaseApiController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function GetObjects(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
if ($this->IsValidEntity($args['entity']) && !$this->IsEntityWithPreventedListing($args['entity']))
|
||||
@@ -44,7 +54,9 @@ class GenericEntityApiController extends BaseApiController
|
||||
$newRow = $this->Database->{$args['entity']}()->createRow($requestBody);
|
||||
$newRow->save();
|
||||
$success = $newRow->isClean();
|
||||
return $this->EmptyApiResponse($response);
|
||||
return $this->ApiResponse(array(
|
||||
'created_object_id' => $this->Database->lastInsertId()
|
||||
));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
@@ -101,6 +113,38 @@ class GenericEntityApiController extends BaseApiController
|
||||
}
|
||||
}
|
||||
|
||||
public function GetUserfields(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $this->ApiResponse($this->UserfieldsService->GetValues($args['entity'], $args['objectId']));
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function SetUserfields(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
try
|
||||
{
|
||||
if ($requestBody === null)
|
||||
{
|
||||
throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)');
|
||||
}
|
||||
|
||||
$this->UserfieldsService->SetValues($args['entity'], $args['objectId'], $requestBody);
|
||||
return $this->EmptyApiResponse($response);
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function IsValidEntity($entity)
|
||||
{
|
||||
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum);
|
||||
|
45
controllers/GenericEntityController.php
Normal file
45
controllers/GenericEntityController.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class GenericEntityController extends BaseController
|
||||
{
|
||||
public function __construct(\Slim\Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function UserfieldsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'userfields', [
|
||||
'userfields' => $this->UserfieldsService->GetAllFields(),
|
||||
'entities' => $this->UserfieldsService->GetEntities()
|
||||
]);
|
||||
}
|
||||
|
||||
public function UserfieldEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
if ($args['userfieldId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'userfieldform', [
|
||||
'mode' => 'create',
|
||||
'userfieldTypes' => $this->UserfieldsService->GetFieldTypes(),
|
||||
'entities' => $this->UserfieldsService->GetEntities()
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'userfieldform', [
|
||||
'mode' => 'edit',
|
||||
'userfield' => $this->UserfieldsService->GetField($args['userfieldId']),
|
||||
'userfieldTypes' => $this->UserfieldsService->GetFieldTypes(),
|
||||
'entities' => $this->UserfieldsService->GetEntities()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\StockService;
|
||||
use \Grocy\Services\UsersService;
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class StockController extends BaseController
|
||||
{
|
||||
@@ -12,9 +13,11 @@ class StockController extends BaseController
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->StockService = new StockService();
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $StockService;
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
@@ -29,7 +32,9 @@ class StockController extends BaseController
|
||||
'currentStockLocations' => $this->StockService->GetCurrentStockLocations(),
|
||||
'missingProducts' => $this->StockService->GetMissingProducts(),
|
||||
'nextXDays' => $nextXDays,
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('products'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('products')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -82,7 +87,9 @@ class StockController extends BaseController
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name')
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('products'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('products')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -98,7 +105,9 @@ class StockController extends BaseController
|
||||
public function LocationsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locations', [
|
||||
'locations' => $this->Database->locations()->orderBy('name')
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('locations'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('locations')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -106,14 +115,18 @@ class StockController extends BaseController
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productgroups', [
|
||||
'productGroups' => $this->Database->product_groups()->orderBy('name'),
|
||||
'products' => $this->Database->products()->orderBy('name')
|
||||
'products' => $this->Database->products()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('product_groups'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('product_groups')
|
||||
]);
|
||||
}
|
||||
|
||||
public function QuantityUnitsList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunits', [
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name')
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('quantity_units'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('quantity_units')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -125,6 +138,7 @@ class StockController extends BaseController
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'productgroups' => $this->Database->product_groups()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('products'),
|
||||
'mode' => 'create'
|
||||
]);
|
||||
}
|
||||
@@ -135,6 +149,7 @@ class StockController extends BaseController
|
||||
'locations' => $this->Database->locations()->orderBy('name'),
|
||||
'quantityunits' => $this->Database->quantity_units()->orderBy('name'),
|
||||
'productgroups' => $this->Database->product_groups()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('products'),
|
||||
'mode' => 'edit'
|
||||
]);
|
||||
}
|
||||
@@ -145,14 +160,16 @@ class StockController extends BaseController
|
||||
if ($args['locationId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locationform', [
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('locations')
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'locationform', [
|
||||
'location' => $this->Database->locations($args['locationId']),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('locations')
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -162,14 +179,16 @@ class StockController extends BaseController
|
||||
if ($args['productGroupId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productgroupform', [
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('product_groups')
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'productgroupform', [
|
||||
'group' => $this->Database->product_groups($args['productGroupId']),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('product_groups')
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -179,14 +198,16 @@ class StockController extends BaseController
|
||||
if ($args['quantityunitId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunitform', [
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('quantity_units')
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'quantityunitform', [
|
||||
'quantityunit' => $this->Database->quantity_units($args['quantityunitId']),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('quantity_units')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ namespace Grocy\Controllers;
|
||||
|
||||
use \Grocy\Services\TasksService;
|
||||
use \Grocy\Services\UsersService;
|
||||
use \Grocy\Services\UserfieldsService;
|
||||
|
||||
class TasksController extends BaseController
|
||||
{
|
||||
@@ -11,9 +12,11 @@ class TasksController extends BaseController
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->TasksService = new TasksService();
|
||||
$this->UserfieldsService = new UserfieldsService();
|
||||
}
|
||||
|
||||
protected $TasksService;
|
||||
protected $UserfieldsService;
|
||||
|
||||
public function Overview(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
@@ -44,7 +47,8 @@ class TasksController extends BaseController
|
||||
return $this->AppContainer->view->render($response, 'taskform', [
|
||||
'mode' => 'create',
|
||||
'taskCategories' => $this->Database->task_categories()->orderBy('name'),
|
||||
'users' => $this->Database->users()->orderBy('username')
|
||||
'users' => $this->Database->users()->orderBy('username'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('tasks')
|
||||
]);
|
||||
}
|
||||
else
|
||||
@@ -53,7 +57,8 @@ class TasksController extends BaseController
|
||||
'task' => $this->Database->tasks($args['taskId']),
|
||||
'mode' => 'edit',
|
||||
'taskCategories' => $this->Database->task_categories()->orderBy('name'),
|
||||
'users' => $this->Database->users()->orderBy('username')
|
||||
'users' => $this->Database->users()->orderBy('username'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('tasks')
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -61,7 +66,9 @@ class TasksController extends BaseController
|
||||
public function TaskCategoriesList(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'taskcategories', [
|
||||
'taskCategories' => $this->Database->task_categories()->orderBy('name')
|
||||
'taskCategories' => $this->Database->task_categories()->orderBy('name'),
|
||||
'userfields' => $this->UserfieldsService->GetFields('task_categories'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('task_categories')
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -70,14 +77,16 @@ class TasksController extends BaseController
|
||||
if ($args['categoryId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'taskcategoryform', [
|
||||
'mode' => 'create'
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('task_categories')
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'taskcategoryform', [
|
||||
'category' => $this->Database->task_categories($args['categoryId']),
|
||||
'mode' => 'edit'
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('task_categories')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
2
data/viewcache/.gitignore
vendored
2
data/viewcache/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
@@ -234,8 +234,22 @@
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "The operation was successful"
|
||||
"200": {
|
||||
"description": "The operation was successful",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"created_object_id": {
|
||||
"type": "number",
|
||||
"format": "integer",
|
||||
"description": "The id of the created object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "The operation was not successful",
|
||||
@@ -438,6 +452,109 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/userfields/{entity}/{objectId}": {
|
||||
"get": {
|
||||
"summary": "Returns all userfields with their values of the given object of the given entity",
|
||||
"tags": [
|
||||
"Generic entity interactions"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "entity",
|
||||
"required": true,
|
||||
"description": "A valid entity name",
|
||||
"schema": {
|
||||
"$ref": "#/components/internalSchemas/ExposedEntity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "objectId",
|
||||
"required": true,
|
||||
"description": "A valid object id of the given entity",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "An entity object",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"description": "Just key/value pairs of userfields"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "The operation was not successful",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GenericErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"summary": "Edits the given userfields of the given object of the given entity",
|
||||
"tags": [
|
||||
"Generic entity interactions"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "entity",
|
||||
"required": true,
|
||||
"description": "A valid entity name",
|
||||
"schema": {
|
||||
"$ref": "#/components/internalSchemas/ExposedEntity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "path",
|
||||
"name": "objectId",
|
||||
"required": true,
|
||||
"description": "A valid object id of the given entity",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"description": "A valid entity object of the entity specified in parameter *entity*",
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"description": "Just key/value pairs of userfields"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "The operation was successful"
|
||||
},
|
||||
"400": {
|
||||
"description": "The operation was not successful",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GenericErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/files/{group}/{fileName}": {
|
||||
"get": {
|
||||
"summary": "Serves the given file",
|
||||
@@ -2030,7 +2147,8 @@
|
||||
"task_categories",
|
||||
"product_groups",
|
||||
"equipment",
|
||||
"api_keys"
|
||||
"api_keys",
|
||||
"userfields"
|
||||
]
|
||||
},
|
||||
"ExposedEntitiesPreventListing": {
|
||||
|
11
localization/en/userfield_types.php
Normal file
11
localization/en/userfield_types.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'text-single-line' => 'Text (single line)',
|
||||
'text-multi-line' => 'Text (multi line)',
|
||||
'number-integral' => 'Number (integral)',
|
||||
'number-decimal' => 'Number (decimal)',
|
||||
'date' => 'Date (without time)',
|
||||
'datetime' => 'Date & time',
|
||||
'checkbox' => 'Checkbox'
|
||||
);
|
31
migrations/0066.sql
Normal file
31
migrations/0066.sql
Normal file
@@ -0,0 +1,31 @@
|
||||
CREATE TABLE userfields (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
entity TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
caption TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
show_as_column_in_tables TINYINT NOT NULL DEFAULT 0,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')),
|
||||
|
||||
UNIQUE(entity, name)
|
||||
);
|
||||
|
||||
CREATE TABLE userfield_values (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
field_id INTEGER NOT NULL,
|
||||
object_id INTEGER NOT NULL,
|
||||
value TEXT NOT NULL,
|
||||
row_created_timestamp DATETIME DEFAULT (datetime('now', 'localtime')),
|
||||
|
||||
UNIQUE(field_id, object_id)
|
||||
);
|
||||
|
||||
CREATE VIEW userfield_values_resolved
|
||||
AS
|
||||
SELECT
|
||||
u.*,
|
||||
uv.object_id,
|
||||
uv.value
|
||||
FROM userfields u
|
||||
JOIN userfield_values uv
|
||||
ON u.id = uv.field_id;
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/batteries', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/batteries');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/batteries/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/batteries');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -57,5 +64,6 @@ $('#battery-form input').keydown(function(event)
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('battery-form');
|
||||
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/chores', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/chores/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -66,6 +73,7 @@ for (var i = 0; i < checkboxValues.length; i++)
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('chore-form');
|
||||
|
||||
|
69
public/viewjs/components/userfieldsform.js
Normal file
69
public/viewjs/components/userfieldsform.js
Normal file
@@ -0,0 +1,69 @@
|
||||
Grocy.Components.UserfieldsForm = { };
|
||||
|
||||
Grocy.Components.UserfieldsForm.Save = function(success, error)
|
||||
{
|
||||
var jsonData = { };
|
||||
|
||||
$("#userfields-form .userfield-input").each(function()
|
||||
{
|
||||
var input = $(this);
|
||||
var fieldName = input.attr("id");
|
||||
var fieldValue = input.val();
|
||||
|
||||
if (input.attr("type") == "checkbox")
|
||||
{
|
||||
jsonData[fieldName] = "0";
|
||||
if (input.is(":checked"))
|
||||
{
|
||||
jsonData[fieldName] = "1";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
jsonData[fieldName] = fieldValue;
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Api.Put('userfields/' + $("#userfields-form").data("entity") + '/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
success();
|
||||
}
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
error();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load = function()
|
||||
{
|
||||
Grocy.Api.Get('userfields/' + $("#userfields-form").data("entity") + '/' + Grocy.EditObjectId,
|
||||
function(result)
|
||||
{
|
||||
$.each(result, function(key, value)
|
||||
{
|
||||
var input = $("#" + key + ".userfield-input");
|
||||
|
||||
if (input.attr("type") == "checkbox" && value == 1)
|
||||
{
|
||||
input.prop("checked", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
input.val(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.log(xhr);
|
||||
}
|
||||
);
|
||||
}
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/locations', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/locations');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/locations/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/locations');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -57,5 +64,6 @@ $('#location-form input').keydown(function (event)
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('location-form');
|
||||
|
@@ -1,4 +1,4 @@
|
||||
$('#save-product-button').on('click', function (e)
|
||||
$('#save-product-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
@@ -26,12 +26,15 @@
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('objects/products', jsonData,
|
||||
function (result)
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
if (jsonData.hasOwnProperty("picture_file_name") && !Grocy.DeleteProductPictureOnSave)
|
||||
{
|
||||
Grocy.Api.UploadFile($("#product-picture")[0].files[0], 'productpictures', jsonData.picture_file_name,
|
||||
function (result)
|
||||
function(result)
|
||||
{
|
||||
window.location.href = redirectDestination;
|
||||
},
|
||||
@@ -46,6 +49,7 @@
|
||||
{
|
||||
window.location.href = redirectDestination;
|
||||
}
|
||||
});
|
||||
},
|
||||
function (xhr)
|
||||
{
|
||||
@@ -73,6 +77,8 @@
|
||||
|
||||
Grocy.Api.Put('objects/products/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
if (jsonData.hasOwnProperty("picture_file_name") && !Grocy.DeleteProductPictureOnSave)
|
||||
{
|
||||
@@ -92,6 +98,7 @@
|
||||
{
|
||||
window.location.href = redirectDestination;
|
||||
}
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -258,6 +265,7 @@ if (Grocy.EditMode === 'create')
|
||||
}
|
||||
}
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
$('.input-group-qu').trigger('change');
|
||||
Grocy.FrontendHelpers.ValidateForm('product-form');
|
||||
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/product_groups', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/productgroups');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/product_groups/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/productgroups');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -57,5 +64,6 @@ $('#product-group-form input').keydown(function (event)
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('product-group-form');
|
||||
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/quantity_units', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/quantityunits');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/quantity_units/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/quantityunits');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -57,5 +64,6 @@ $('#quantityunit-form input').keydown(function(event)
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('quantityunit-form');
|
||||
|
@@ -9,8 +9,12 @@
|
||||
{
|
||||
Grocy.Api.Post('objects/task_categories', jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/taskcategories');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -23,8 +27,11 @@
|
||||
{
|
||||
Grocy.Api.Put('objects/task_categories/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/taskcategories');
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
@@ -57,5 +64,6 @@ $('#task-category-form input').keydown(function (event)
|
||||
}
|
||||
});
|
||||
|
||||
Grocy.Components.UserfieldsForm.Load();
|
||||
$('#name').focus();
|
||||
Grocy.FrontendHelpers.ValidateForm('task-category-form');
|
||||
|
74
public/viewjs/userfieldform.js
Normal file
74
public/viewjs/userfieldform.js
Normal file
@@ -0,0 +1,74 @@
|
||||
$('#save-userfield-button').on('click', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#userfield-form').serializeJSON();
|
||||
Grocy.FrontendHelpers.BeginUiBusy("userfield-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
{
|
||||
Grocy.Api.Post('objects/userfields', jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/userfields');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("userfield-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Grocy.Api.Put('objects/userfields/' + Grocy.EditObjectId, jsonData,
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/userfields');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy("userfield-form");
|
||||
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$('#userfield-form input').keyup(function(event)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('userfield-form');
|
||||
});
|
||||
|
||||
$('#userfield-form select').change(function(event)
|
||||
{
|
||||
Grocy.FrontendHelpers.ValidateForm('userfield-form');
|
||||
});
|
||||
|
||||
$('#userfield-form input').keydown(function(event)
|
||||
{
|
||||
if (event.keyCode === 13) //Enter
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
if (document.getElementById('userfield-form').checkValidity() === false) //There is at least one validation error
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#save-userfield-button').click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#entity').focus();
|
||||
|
||||
if (typeof GetUriParam("entity") !== "undefined")
|
||||
{
|
||||
$("#entity").val(GetUriParam("entity"));
|
||||
$("#entity").trigger("change");
|
||||
$('#name').focus();
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('userfield-form');
|
86
public/viewjs/userfields.js
Normal file
86
public/viewjs/userfields.js
Normal file
@@ -0,0 +1,86 @@
|
||||
var userfieldsTable = $('#userfields-table').DataTable({
|
||||
'paginate': false,
|
||||
'order': [[1, 'asc']],
|
||||
'columnDefs': [
|
||||
{ 'orderable': false, 'targets': 0 }
|
||||
],
|
||||
'language': JSON.parse(L('datatables_localization')),
|
||||
'scrollY': false,
|
||||
'colReorder': true,
|
||||
'stateSave': true,
|
||||
'stateSaveParams': function(settings, data)
|
||||
{
|
||||
data.search.search = "";
|
||||
|
||||
data.columns.forEach(column =>
|
||||
{
|
||||
column.search.search = "";
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#userfields-table tbody').removeClass("d-none");
|
||||
userfieldsTable.columns.adjust().draw();
|
||||
|
||||
$("#search").on("keyup", function()
|
||||
{
|
||||
var value = $(this).val();
|
||||
if (value === "all")
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
userfieldsTable.search(value).draw();
|
||||
});
|
||||
|
||||
$("#entity-filter").on("change", function()
|
||||
{
|
||||
var value = $("#entity-filter option:selected").text();
|
||||
if (value === L("All"))
|
||||
{
|
||||
value = "";
|
||||
}
|
||||
|
||||
userfieldsTable.column(1).search(value).draw();
|
||||
});
|
||||
|
||||
$(document).on('click', '.userfield-delete-button', function (e)
|
||||
{
|
||||
var objectName = $(e.currentTarget).attr('data-userfield-name');
|
||||
var objectId = $(e.currentTarget).attr('data-userfield-id');
|
||||
|
||||
bootbox.confirm({
|
||||
message: L('Are you sure to delete user field "#1"?', objectName),
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: L('Yes'),
|
||||
className: 'btn-success'
|
||||
},
|
||||
cancel: {
|
||||
label: L('No'),
|
||||
className: 'btn-danger'
|
||||
}
|
||||
},
|
||||
callback: function(result)
|
||||
{
|
||||
if (result === true)
|
||||
{
|
||||
Grocy.Api.Delete('objects/userfields/' + objectId, {},
|
||||
function(result)
|
||||
{
|
||||
window.location.href = U('/userfields');
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (typeof GetUriParam("entity") !== "undefined")
|
||||
{
|
||||
$("#entity-filter").val(GetUriParam("entity"));
|
||||
$("#entity-filter").trigger("change");
|
||||
}
|
@@ -16,6 +16,10 @@ $app->group('', function()
|
||||
$this->post('/login', 'LoginControllerInstance:ProcessLogin')->setName('login');
|
||||
$this->get('/logout', 'LoginControllerInstance:Logout');
|
||||
|
||||
// Generic entity interaction
|
||||
$this->get('/userfields', '\Grocy\Controllers\GenericEntityController:UserfieldsList');
|
||||
$this->get('/userfield/{userfieldId}', '\Grocy\Controllers\GenericEntityController:UserfieldEditForm');
|
||||
|
||||
// User routes
|
||||
$this->get('/users', '\Grocy\Controllers\UsersController:UsersList');
|
||||
$this->get('/user/{userId}', '\Grocy\Controllers\UsersController:UserEditForm');
|
||||
@@ -119,6 +123,8 @@ $app->group('/api', function()
|
||||
$this->post('/objects/{entity}', '\Grocy\Controllers\GenericEntityApiController:AddObject');
|
||||
$this->put('/objects/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:EditObject');
|
||||
$this->delete('/objects/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:DeleteObject');
|
||||
$this->get('/userfields/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:GetUserfields');
|
||||
$this->put('/userfields/{entity}/{objectId}', '\Grocy\Controllers\GenericEntityApiController:SetUserfields');
|
||||
|
||||
// Files
|
||||
$this->put('/files/{group}/{fileName}', '\Grocy\Controllers\FilesApiController:UploadFile');
|
||||
|
@@ -28,6 +28,7 @@ class LocalizationService
|
||||
'strings.php',
|
||||
'stock_transaction_types.php',
|
||||
'chore_types.php',
|
||||
'userfield_types.php',
|
||||
'component_translations.php',
|
||||
'demo_data.php'
|
||||
);
|
||||
|
121
services/UserfieldsService.php
Normal file
121
services/UserfieldsService.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Grocy\Services;
|
||||
|
||||
class UserfieldsService extends BaseService
|
||||
{
|
||||
const USERFIELD_TYPE_SINGLE_LINE_TEXT = 'text-single-line';
|
||||
const USERFIELD_TYPE_SINGLE_MULTILINE_TEXT = 'text-multi-line';
|
||||
const USERFIELD_TYPE_INTEGRAL_NUMBER = 'number-integral';
|
||||
const USERFIELD_TYPE_DECIMAL_NUMBER = 'number-decimal';
|
||||
const USERFIELD_TYPE_DATE = 'date';
|
||||
const USERFIELD_TYPE_DATETIME = 'datetime';
|
||||
const USERFIELD_TYPE_CHECKBOX = 'checkbox';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->OpenApiSpec = json_decode(file_get_contents(__DIR__ . '/../grocy.openapi.json'));
|
||||
}
|
||||
|
||||
protected $OpenApiSpec;
|
||||
|
||||
public function GetFields($entity)
|
||||
{
|
||||
if (!$this->IsValidEntity($entity))
|
||||
{
|
||||
throw new \Exception('Entity does not exist or is not exposed');
|
||||
}
|
||||
|
||||
return $this->Database->userfields()->where('entity', $entity)->orderBy('name')->fetchAll();
|
||||
}
|
||||
|
||||
public function GetField($fieldId)
|
||||
{
|
||||
return $this->Database->userfields($fieldId);
|
||||
}
|
||||
|
||||
public function GetAllFields()
|
||||
{
|
||||
return $this->Database->userfields()->orderBy('name')->fetchAll();
|
||||
}
|
||||
|
||||
public function GetValues($entity, $objectId)
|
||||
{
|
||||
if (!$this->IsValidEntity($entity))
|
||||
{
|
||||
throw new \Exception('Entity does not exist or is not exposed');
|
||||
}
|
||||
|
||||
$userfields = $this->Database->userfield_values_resolved()->where('entity = :1 AND object_id = :2', $entity, $objectId)->orderBy('name')->fetchAll();
|
||||
$userfieldKeyValuePairs = array();
|
||||
foreach ($userfields as $userfield)
|
||||
{
|
||||
$userfieldKeyValuePairs[$userfield->name] = $userfield->value;
|
||||
}
|
||||
|
||||
return $userfieldKeyValuePairs;
|
||||
}
|
||||
|
||||
public function GetAllValues($entity)
|
||||
{
|
||||
if (!$this->IsValidEntity($entity))
|
||||
{
|
||||
throw new \Exception('Entity does not exist or is not exposed');
|
||||
}
|
||||
|
||||
return $this->Database->userfield_values_resolved()->where('entity', $entity)->orderBy('name')->fetchAll();
|
||||
}
|
||||
|
||||
public function SetValues($entity, $objectId, $userfields)
|
||||
{
|
||||
if (!$this->IsValidEntity($entity))
|
||||
{
|
||||
throw new \Exception('Entity does not exist or is not exposed');
|
||||
}
|
||||
|
||||
foreach ($userfields as $key => $value)
|
||||
{
|
||||
$fieldRow = $this->Database->userfields()->where('entity = :1 AND name = :2', $entity, $key)->fetch();
|
||||
|
||||
if ($fieldRow === null)
|
||||
{
|
||||
throw new \Exception("Field $key is not a valid userfield of the given entity");
|
||||
}
|
||||
|
||||
$fieldId = $fieldRow->id;
|
||||
|
||||
$alreadyExistingEntry = $this->Database->userfield_values()->where('field_id = :1 AND object_id = :2', $fieldId, $objectId)->fetch();
|
||||
if ($alreadyExistingEntry) // Update
|
||||
{
|
||||
$alreadyExistingEntry->update(array(
|
||||
'value' => $value
|
||||
));
|
||||
}
|
||||
else // Insert
|
||||
{
|
||||
$newRow = $this->Database->userfield_values()->createRow(array(
|
||||
'field_id' => $fieldId,
|
||||
'object_id' => $objectId,
|
||||
'value' => $value
|
||||
));
|
||||
$newRow->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function GetEntities()
|
||||
{
|
||||
return $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum;
|
||||
}
|
||||
|
||||
public function GetFieldTypes()
|
||||
{
|
||||
return GetClassConstants('\Grocy\Services\UserfieldsService');
|
||||
}
|
||||
|
||||
private function IsValidEntity($entity)
|
||||
{
|
||||
return in_array($entity, $this->OpenApiSpec->components->internalSchemas->ExposedEntity->enum);
|
||||
}
|
||||
}
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/battery/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=batteries') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -33,6 +36,11 @@
|
||||
<th>{{ $L('Description') }}</th>
|
||||
<th>{{ $L('Used in') }}</th>
|
||||
<th>{{ $L('Charge cycle interval (days)') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -58,6 +66,12 @@
|
||||
<td>
|
||||
{{ $battery->charge_interval_days }}
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $battery->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -46,6 +46,11 @@
|
||||
<th>{{ $L('Last charged') }}</th>
|
||||
<th>{{ $L('Next planned charge cycle') }}</th>
|
||||
<th class="d-none">Hidden status</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -92,6 +97,12 @@
|
||||
<td class="d-none">
|
||||
"@if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $curentBatteryEntry->next_estimated_charge_time < date('Y-m-d H:i:s')) overdue @elseif(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0 && $curentBatteryEntry->next_estimated_charge_time < date('Y-m-d H:i:s', strtotime("+$nextXDays days"))) duesoon @endif
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $curentBatteryEntry->battery_id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -47,6 +47,11 @@
|
||||
'invalidFeedback' => $L('This cannot be negative')
|
||||
))
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'batteries'
|
||||
))
|
||||
|
||||
<button id="save-battery-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
@@ -87,6 +87,11 @@
|
||||
|
||||
<input type="hidden" id="period_config" name="period_config" value="@if($mode == 'edit'){{ $chore->period_config }}@endif">
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'chores'
|
||||
))
|
||||
|
||||
<button id="save-chore-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/chore/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=chores') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,6 +35,11 @@
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Period type') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -54,6 +62,12 @@
|
||||
<td>
|
||||
{{ $chore->description }}
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $chore->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -46,6 +46,11 @@
|
||||
<th>{{ $L('Next estimated tracking') }}</th>
|
||||
<th>{{ $L('Last tracked') }}</th>
|
||||
<th class="d-none">Hidden status</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -92,6 +97,12 @@
|
||||
<td class="d-none">
|
||||
@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s')) overdue @elseif(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s', strtotime("+$nextXDays days"))) duesoon @endif
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $curentChoreEntry->chore_id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
16
views/components/userfields_tbody.blade.php
Normal file
16
views/components/userfields_tbody.blade.php
Normal file
@@ -0,0 +1,16 @@
|
||||
@push('componentScripts')
|
||||
<script src="{{ $U('/viewjs/components/userfieldsform.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@if(count($userfields) > 0)
|
||||
|
||||
@foreach($userfields as $userfield)
|
||||
|
||||
@if($userfield->show_as_column_in_tables == 1)
|
||||
@php $userfieldObject = FindObjectInArrayByPropertyValue($userfieldValues, 'name', $userfield->name) @endphp
|
||||
<td>@if($userfieldObject !== null){{ $userfieldObject->value }}@endif</td>
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
|
||||
@endif
|
15
views/components/userfields_thead.blade.php
Normal file
15
views/components/userfields_thead.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@push('componentScripts')
|
||||
<script src="{{ $U('/viewjs/components/userfieldsform.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@if(count($userfields) > 0)
|
||||
|
||||
@foreach($userfields as $userfield)
|
||||
|
||||
@if($userfield->show_as_column_in_tables == 1)
|
||||
<th>{{ $userfield->name }}</th>
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
|
||||
@endif
|
32
views/components/userfieldsform.blade.php
Normal file
32
views/components/userfieldsform.blade.php
Normal file
@@ -0,0 +1,32 @@
|
||||
@push('componentScripts')
|
||||
<script src="{{ $U('/viewjs/components/userfieldsform.js', true) }}?v={{ $version }}"></script>
|
||||
@endpush
|
||||
|
||||
@if(count($userfields) > 0)
|
||||
|
||||
<div id="userfields-form" data-entity="{{ $entity }}" class="border border-info p-2 mb-2" novalidate>
|
||||
<h2 class="small">{{ $L('Userfields') }}</h2>
|
||||
|
||||
@foreach($userfields as $userfield)
|
||||
|
||||
@if($userfield->type == \Grocy\Services\UserfieldsService::USERFIELD_TYPE_SINGLE_LINE_TEXT)
|
||||
<div class="form-group">
|
||||
<label for="name">{{ $userfield->caption }}</label>
|
||||
<input type="text" class="form-control userfield-input" id="{{ $userfield->name }}" value="">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($userfield->type == \Grocy\Services\UserfieldsService::USERFIELD_TYPE_CHECKBOX)
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input userfield-input" type="checkbox" id="{{ $userfield->name }}" value="1">
|
||||
<label class="form-check-label" for="{{ $userfield->name }}">{{ $userfield->caption }}</label>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
@endif
|
@@ -32,6 +32,11 @@
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $location->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'locations'
|
||||
))
|
||||
|
||||
<button id="save-location-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/location/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=locations') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -31,6 +34,11 @@
|
||||
<th class="border-right"></th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -50,6 +58,12 @@
|
||||
<td>
|
||||
{{ $location->description }}
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $location->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -187,8 +187,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'products'
|
||||
))
|
||||
|
||||
<button id="save-product-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
|
@@ -32,6 +32,11 @@
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $group->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'product_groups'
|
||||
))
|
||||
|
||||
<button id="save-product-group-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/productgroup/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=product_groups') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,6 +35,10 @@
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
<th>{{ $L('Product count') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -57,6 +64,12 @@
|
||||
<i class="fas fa-external-link-alt"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $productGroup->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/product/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=products') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/stocksettings#productpresets') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Presets for new products') }}
|
||||
</a>
|
||||
@@ -48,6 +51,11 @@
|
||||
<th>{{ $L('QU stock') }}</th>
|
||||
<th>{{ $L('QU factor') }}</th>
|
||||
<th>{{ $L('Product group') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -82,6 +90,12 @@
|
||||
<td>
|
||||
@if(!empty($product->product_group_id)) {{ FindObjectInArrayByPropertyValue($productGroups, 'id', $product->product_group_id)->name }} @endif
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $product->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -37,6 +37,11 @@
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $quantityunit->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'quantity_units'
|
||||
))
|
||||
|
||||
<button id="save-quantityunit-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/quantityunit/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=quantity_units') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -31,6 +34,10 @@
|
||||
<th class="border-right"></th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -50,6 +57,12 @@
|
||||
<td>
|
||||
{{ $quantityunit->description }}
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $quantityunit->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -77,6 +77,11 @@
|
||||
<th class="d-none">Hidden location</th>
|
||||
<th class="d-none">Hidden status</th>
|
||||
<th class="d-none">Hidden product group</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -143,6 +148,12 @@
|
||||
<td class="d-none">
|
||||
@if($productGroup !== null){{ $productGroup->name }}@endif
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $currentStockEntry->product_id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -12,6 +12,9 @@
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/taskcategory/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
<a class="btn btn-outline-secondary" href="{{ $U('/userfields?entity=task_categories') }}">
|
||||
<i class="fas fa-sliders-h"></i> {{ $L('Configure userfields') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
@@ -31,6 +34,11 @@
|
||||
<th class="border-right"></th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Description') }}</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
'userfields' => $userfields
|
||||
))
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@@ -50,6 +58,12 @@
|
||||
<td>
|
||||
{{ $taskCategory->description }}
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
'userfields' => $userfields,
|
||||
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $taskCategory->id)
|
||||
))
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
@@ -32,6 +32,11 @@
|
||||
<textarea class="form-control" rows="2" id="description" name="description">@if($mode == 'edit'){{ $category->description }}@endif</textarea>
|
||||
</div>
|
||||
|
||||
@include('components.userfieldsform', array(
|
||||
'userfields' => $userfields,
|
||||
'entity' => 'task_categories'
|
||||
))
|
||||
|
||||
<button id="save-task-category-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
|
71
views/userfieldform.blade.php
Normal file
71
views/userfieldform.blade.php
Normal file
@@ -0,0 +1,71 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@if($mode == 'edit')
|
||||
@section('title', $L('Edit userfield'))
|
||||
@else
|
||||
@section('title', $L('Create userfield'))
|
||||
@endif
|
||||
|
||||
@section('viewJsName', 'userfieldform')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
<h1>@yield('title')</h1>
|
||||
|
||||
<script>Grocy.EditMode = '{{ $mode }}';</script>
|
||||
|
||||
@if($mode == 'edit')
|
||||
<script>Grocy.EditObjectId = {{ $userfield->id }};</script>
|
||||
@endif
|
||||
|
||||
<form id="userfield-form" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="entity">{{ $L('Entity') }}</label>
|
||||
<select required class="form-control" id="entity" name="entity">
|
||||
<option></option>
|
||||
@foreach($entities as $entity)
|
||||
<option @if($mode == 'edit' && $userfield->entity == $entity) selected="selected" @endif value="{{ $entity }}">{{ $entity }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $L('A entity is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">{{ $L('Name') }}</label>
|
||||
<input type="text" class="form-control" required id="name" name="name" value="@if($mode == 'edit'){{ $userfield->name }}@endif">
|
||||
<div class="invalid-feedback">{{ $L('A name is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name">{{ $L('Caption') }}</label>
|
||||
<input type="text" class="form-control" required id="caption" name="caption" value="@if($mode == 'edit'){{ $userfield->caption }}@endif">
|
||||
<div class="invalid-feedback">{{ $L('A caption is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="entity">{{ $L('Type') }}</label>
|
||||
<select required class="form-control" id="type" name="type">
|
||||
<option></option>
|
||||
@foreach($userfieldTypes as $userfieldType)
|
||||
<option @if($mode == 'edit' && $userfield->type == $userfieldType) selected="selected" @endif value="{{ $userfieldType }}">{{ $L($userfieldType) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $L('A type is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="show_as_column_in_tables" value="0">
|
||||
<input @if($mode == 'edit' && $userfield->show_as_column_in_tables == 1) checked @endif class="form-check-input" type="checkbox" id="show_as_column_in_tables" name="show_as_column_in_tables" value="1">
|
||||
<label class="form-check-label" for="show_as_column_in_tables">{{ $L('Show as column in tables') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="save-userfield-button" class="btn btn-success">{{ $L('Save') }}</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
76
views/userfields.blade.php
Normal file
76
views/userfields.blade.php
Normal file
@@ -0,0 +1,76 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title', $L('Userfields'))
|
||||
@section('activeNav', 'userfields')
|
||||
@section('viewJsName', 'userfields')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1>
|
||||
@yield('title')
|
||||
<a class="btn btn-outline-dark" href="{{ $U('/userfield/new') }}">
|
||||
<i class="fas fa-plus"></i> {{ $L('Add') }}
|
||||
</a>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="search">{{ $L('Search') }}</label> <i class="fas fa-search"></i>
|
||||
<input type="text" class="form-control" id="search">
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-6 col-xl-3">
|
||||
<label for="entity-filter">{{ $L('Filter by entity') }}</label> <i class="fas fa-filter"></i>
|
||||
<select class="form-control" id="entity-filter">
|
||||
<option value="all">{{ $L('All') }}</option>
|
||||
@foreach($entities as $entity)
|
||||
<option value="{{ $entity }}">{{ $entity }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table id="userfields-table" class="table table-sm table-striped dt-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border-right"></th>
|
||||
<th>{{ $L('Entity') }}</th>
|
||||
<th>{{ $L('Name') }}</th>
|
||||
<th>{{ $L('Caption') }}</th>
|
||||
<th>{{ $L('Type') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="d-none">
|
||||
@foreach($userfields as $userfield)
|
||||
<tr>
|
||||
<td class="fit-content border-right">
|
||||
<a class="btn btn-info btn-sm" href="{{ $U('/userfield/') }}{{ $userfield->id }}">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<a class="btn btn-danger btn-sm userfield-delete-button" href="#" data-userfield-id="{{ $userfield->id }}" data-userfield-name="{{ $userfield->name }}">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{ $userfield->entity }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $userfield->name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $userfield->caption }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $L($userfield->type) }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
Reference in New Issue
Block a user