show only devices wb via api
This commit is contained in:
parent
a6c84ae588
commit
31abdf55e2
|
@ -3,28 +3,33 @@ import uuid
|
||||||
from itertools import filterfalse
|
from itertools import filterfalse
|
||||||
|
|
||||||
import marshmallow
|
import marshmallow
|
||||||
from flask import g, current_app as app, render_template, request, Response
|
from flask import Response
|
||||||
|
from flask import current_app as app
|
||||||
|
from flask import g, render_template, request
|
||||||
from flask.json import jsonify
|
from flask.json import jsonify
|
||||||
from flask_sqlalchemy import Pagination
|
from flask_sqlalchemy import Pagination
|
||||||
|
from marshmallow import Schema as MarshmallowSchema
|
||||||
|
from marshmallow import fields
|
||||||
|
from marshmallow import fields as f
|
||||||
|
from marshmallow import validate as v
|
||||||
from sqlalchemy.util import OrderedSet
|
from sqlalchemy.util import OrderedSet
|
||||||
from marshmallow import fields, fields as f, validate as v, Schema as MarshmallowSchema
|
|
||||||
from teal import query
|
from teal import query
|
||||||
from teal.db import ResourceNotFound
|
|
||||||
from teal.cache import cache
|
from teal.cache import cache
|
||||||
from teal.resource import View
|
from teal.db import ResourceNotFound
|
||||||
from teal.marshmallow import ValidationError
|
from teal.marshmallow import ValidationError
|
||||||
|
from teal.resource import View
|
||||||
|
|
||||||
from ereuse_devicehub import auth
|
from ereuse_devicehub import auth
|
||||||
from ereuse_devicehub.db import db
|
from ereuse_devicehub.db import db
|
||||||
from ereuse_devicehub.query import SearchQueryParser, things_response
|
from ereuse_devicehub.query import SearchQueryParser, things_response
|
||||||
from ereuse_devicehub.resources import search
|
from ereuse_devicehub.resources import search
|
||||||
from ereuse_devicehub.resources.action import models as actions
|
from ereuse_devicehub.resources.action import models as actions
|
||||||
|
from ereuse_devicehub.resources.action.models import Trade
|
||||||
from ereuse_devicehub.resources.device import states
|
from ereuse_devicehub.resources.device import states
|
||||||
from ereuse_devicehub.resources.device.models import Device, Manufacturer, Computer
|
from ereuse_devicehub.resources.device.models import Computer, Device, Manufacturer
|
||||||
from ereuse_devicehub.resources.device.search import DeviceSearch
|
from ereuse_devicehub.resources.device.search import DeviceSearch
|
||||||
from ereuse_devicehub.resources.enums import SnapshotSoftware
|
from ereuse_devicehub.resources.enums import SnapshotSoftware
|
||||||
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
|
from ereuse_devicehub.resources.lot.models import LotDeviceDescendants
|
||||||
from ereuse_devicehub.resources.action.models import Trade
|
|
||||||
from ereuse_devicehub.resources.tag.model import Tag
|
from ereuse_devicehub.resources.tag.model import Tag
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,15 +66,16 @@ class Filters(query.Query):
|
||||||
manufacturer = query.ILike(Device.manufacturer)
|
manufacturer = query.ILike(Device.manufacturer)
|
||||||
serialNumber = query.ILike(Device.serial_number)
|
serialNumber = query.ILike(Device.serial_number)
|
||||||
# todo test query for rating (and possibly other filters)
|
# todo test query for rating (and possibly other filters)
|
||||||
rating = query.Join((Device.id == actions.ActionWithOneDevice.device_id)
|
rating = query.Join(
|
||||||
& (actions.ActionWithOneDevice.id == actions.Rate.id),
|
(Device.id == actions.ActionWithOneDevice.device_id)
|
||||||
RateQ)
|
& (actions.ActionWithOneDevice.id == actions.Rate.id),
|
||||||
|
RateQ,
|
||||||
|
)
|
||||||
tag = query.Join(Device.id == Tag.device_id, TagQ)
|
tag = query.Join(Device.id == Tag.device_id, TagQ)
|
||||||
# todo This part of the query is really slow
|
# todo This part of the query is really slow
|
||||||
# And forces usage of distinct, as it returns many rows
|
# And forces usage of distinct, as it returns many rows
|
||||||
# due to having multiple paths to the same
|
# due to having multiple paths to the same
|
||||||
lot = query.Join((Device.id == LotDeviceDescendants.device_id),
|
lot = query.Join((Device.id == LotDeviceDescendants.device_id), LotQ)
|
||||||
LotQ)
|
|
||||||
|
|
||||||
|
|
||||||
class Sorting(query.Sort):
|
class Sorting(query.Sort):
|
||||||
|
@ -104,12 +110,15 @@ class DeviceView(View):
|
||||||
return super().get(id)
|
return super().get(id)
|
||||||
|
|
||||||
def patch(self, id):
|
def patch(self, id):
|
||||||
dev = Device.query.filter_by(id=id, owner_id=g.user.id, active=True).one()
|
dev = Device.query.filter_by(
|
||||||
|
id=id, owner_id=g.user.id, active=True, placeholder=None
|
||||||
|
).one()
|
||||||
if isinstance(dev, Computer):
|
if isinstance(dev, Computer):
|
||||||
resource_def = app.resources['Computer']
|
resource_def = app.resources['Computer']
|
||||||
# TODO check how to handle the 'actions_one'
|
# TODO check how to handle the 'actions_one'
|
||||||
patch_schema = resource_def.SCHEMA(
|
patch_schema = resource_def.SCHEMA(
|
||||||
only=['transfer_state', 'actions_one'], partial=True)
|
only=['transfer_state', 'actions_one'], partial=True
|
||||||
|
)
|
||||||
json = request.get_json(schema=patch_schema)
|
json = request.get_json(schema=patch_schema)
|
||||||
# TODO check how to handle the 'actions_one'
|
# TODO check how to handle the 'actions_one'
|
||||||
json.pop('actions_one')
|
json.pop('actions_one')
|
||||||
|
@ -129,12 +138,16 @@ class DeviceView(View):
|
||||||
return self.one_private(id)
|
return self.one_private(id)
|
||||||
|
|
||||||
def one_public(self, id: int):
|
def one_public(self, id: int):
|
||||||
device = Device.query.filter_by(devicehub_id=id, active=True).one()
|
device = Device.query.filter_by(
|
||||||
|
devicehub_id=id, active=True, placeholder=None
|
||||||
|
).one()
|
||||||
return render_template('devices/layout.html', device=device, states=states)
|
return render_template('devices/layout.html', device=device, states=states)
|
||||||
|
|
||||||
@auth.Auth.requires_auth
|
@auth.Auth.requires_auth
|
||||||
def one_private(self, id: str):
|
def one_private(self, id: str):
|
||||||
device = Device.query.filter_by(devicehub_id=id, owner_id=g.user.id, active=True).first()
|
device = Device.query.filter_by(
|
||||||
|
devicehub_id=id, owner_id=g.user.id, active=True, placeholder=None
|
||||||
|
).first()
|
||||||
if not device:
|
if not device:
|
||||||
return self.one_public(id)
|
return self.one_public(id)
|
||||||
return self.schema.jsonify(device)
|
return self.schema.jsonify(device)
|
||||||
|
@ -148,7 +161,11 @@ class DeviceView(View):
|
||||||
devices = query.paginate(page=args['page'], per_page=30) # type: Pagination
|
devices = query.paginate(page=args['page'], per_page=30) # type: Pagination
|
||||||
return things_response(
|
return things_response(
|
||||||
self.schema.dump(devices.items, many=True, nested=1),
|
self.schema.dump(devices.items, many=True, nested=1),
|
||||||
devices.page, devices.per_page, devices.total, devices.prev_num, devices.next_num
|
devices.page,
|
||||||
|
devices.per_page,
|
||||||
|
devices.total,
|
||||||
|
devices.prev_num,
|
||||||
|
devices.next_num,
|
||||||
)
|
)
|
||||||
|
|
||||||
def query(self, args):
|
def query(self, args):
|
||||||
|
@ -158,9 +175,11 @@ class DeviceView(View):
|
||||||
|
|
||||||
trades_dev_ids = {d.id for t in trades for d in t.devices}
|
trades_dev_ids = {d.id for t in trades for d in t.devices}
|
||||||
|
|
||||||
query = Device.query.filter(Device.active == True).filter(
|
query = (
|
||||||
(Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids))
|
Device.query.filter(Device.active == True, Device.placeholder == None)
|
||||||
).distinct()
|
.filter((Device.owner_id == g.user.id) | (Device.id.in_(trades_dev_ids)))
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
|
||||||
unassign = args.get('unassign', None)
|
unassign = args.get('unassign', None)
|
||||||
search_p = args.get('search', None)
|
search_p = args.get('search', None)
|
||||||
|
@ -168,18 +187,22 @@ class DeviceView(View):
|
||||||
properties = DeviceSearch.properties
|
properties = DeviceSearch.properties
|
||||||
tags = DeviceSearch.tags
|
tags = DeviceSearch.tags
|
||||||
devicehub_ids = DeviceSearch.devicehub_ids
|
devicehub_ids = DeviceSearch.devicehub_ids
|
||||||
query = query.join(DeviceSearch).filter(
|
query = (
|
||||||
search.Search.match(properties, search_p) |
|
query.join(DeviceSearch)
|
||||||
search.Search.match(tags, search_p) |
|
.filter(
|
||||||
search.Search.match(devicehub_ids, search_p)
|
search.Search.match(properties, search_p)
|
||||||
).order_by(
|
| search.Search.match(tags, search_p)
|
||||||
search.Search.rank(properties, search_p) +
|
| search.Search.match(devicehub_ids, search_p)
|
||||||
search.Search.rank(tags, search_p) +
|
)
|
||||||
search.Search.rank(devicehub_ids, search_p)
|
.order_by(
|
||||||
|
search.Search.rank(properties, search_p)
|
||||||
|
+ search.Search.rank(tags, search_p)
|
||||||
|
+ search.Search.rank(devicehub_ids, search_p)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if unassign:
|
if unassign:
|
||||||
subquery = LotDeviceDescendants.query.with_entities(
|
subquery = LotDeviceDescendants.query.with_entities(
|
||||||
LotDeviceDescendants.device_id
|
LotDeviceDescendants.device_id
|
||||||
)
|
)
|
||||||
query = query.filter(Device.id.notin_(subquery))
|
query = query.filter(Device.id.notin_(subquery))
|
||||||
return query.filter(*args['filter']).order_by(*args['sort'])
|
return query.filter(*args['filter']).order_by(*args['sort'])
|
||||||
|
@ -221,10 +244,16 @@ class DeviceMergeView(View):
|
||||||
raise ValidationError('The devices is not the same type.')
|
raise ValidationError('The devices is not the same type.')
|
||||||
|
|
||||||
# Adding actions of self.with_device
|
# Adding actions of self.with_device
|
||||||
with_actions_one = [a for a in self.with_device.actions
|
with_actions_one = [
|
||||||
if isinstance(a, actions.ActionWithOneDevice)]
|
a
|
||||||
with_actions_multiple = [a for a in self.with_device.actions
|
for a in self.with_device.actions
|
||||||
if isinstance(a, actions.ActionWithMultipleDevices)]
|
if isinstance(a, actions.ActionWithOneDevice)
|
||||||
|
]
|
||||||
|
with_actions_multiple = [
|
||||||
|
a
|
||||||
|
for a in self.with_device.actions
|
||||||
|
if isinstance(a, actions.ActionWithMultipleDevices)
|
||||||
|
]
|
||||||
|
|
||||||
# Moving the tags from `with_device` to `base_device`
|
# Moving the tags from `with_device` to `base_device`
|
||||||
# Union of tags the device had plus the (potentially) new ones
|
# Union of tags the device had plus the (potentially) new ones
|
||||||
|
@ -269,20 +298,22 @@ class DeviceMergeView(View):
|
||||||
|
|
||||||
class ManufacturerView(View):
|
class ManufacturerView(View):
|
||||||
class FindArgs(marshmallow.Schema):
|
class FindArgs(marshmallow.Schema):
|
||||||
search = marshmallow.fields.Str(required=True,
|
search = marshmallow.fields.Str(
|
||||||
# Disallow like operators
|
required=True,
|
||||||
validate=lambda x: '%' not in x and '_' not in x)
|
# Disallow like operators
|
||||||
|
validate=lambda x: '%' not in x and '_' not in x,
|
||||||
|
)
|
||||||
|
|
||||||
@cache(datetime.timedelta(days=1))
|
@cache(datetime.timedelta(days=1))
|
||||||
def find(self, args: dict):
|
def find(self, args: dict):
|
||||||
search = args['search']
|
search = args['search']
|
||||||
manufacturers = Manufacturer.query \
|
manufacturers = Manufacturer.query.filter(
|
||||||
.filter(Manufacturer.name.ilike(search + '%')) \
|
Manufacturer.name.ilike(search + '%')
|
||||||
.paginate(page=1, per_page=6) # type: Pagination
|
).paginate(
|
||||||
|
page=1, per_page=6
|
||||||
|
) # type: Pagination
|
||||||
return jsonify(
|
return jsonify(
|
||||||
items=app.resources[Manufacturer.t].schema.dump(
|
items=app.resources[Manufacturer.t].schema.dump(
|
||||||
manufacturers.items,
|
manufacturers.items, many=True, nested=1
|
||||||
many=True,
|
|
||||||
nested=1
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
Reference in New Issue