mirror of https://github.com/veops/cmdb.git
feat(api): My subscription supports CIType sorting
This commit is contained in:
parent
691051c254
commit
f355ca4bcc
|
@ -11,6 +11,8 @@ from api.models.cmdb import Attribute
|
||||||
from api.models.cmdb import CI
|
from api.models.cmdb import CI
|
||||||
from api.models.cmdb import CIType
|
from api.models.cmdb import CIType
|
||||||
from api.models.cmdb import CITypeAttribute
|
from api.models.cmdb import CITypeAttribute
|
||||||
|
from api.models.cmdb import PreferenceShowAttributes
|
||||||
|
from api.models.cmdb import PreferenceTreeView
|
||||||
from api.models.cmdb import RelationType
|
from api.models.cmdb import RelationType
|
||||||
|
|
||||||
|
|
||||||
|
@ -228,8 +230,9 @@ class CITypeAttributeCache(object):
|
||||||
|
|
||||||
|
|
||||||
class CMDBCounterCache(object):
|
class CMDBCounterCache(object):
|
||||||
KEY = 'CMDB::Counter'
|
KEY = 'CMDB::Counter::dashboard'
|
||||||
KEY2 = 'CMDB::Counter2'
|
KEY2 = 'CMDB::Counter::adc'
|
||||||
|
KEY3 = 'CMDB::Counter::sub'
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls):
|
def get(cls):
|
||||||
|
@ -450,3 +453,29 @@ class CMDBCounterCache(object):
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_adc_counter(cls):
|
def get_adc_counter(cls):
|
||||||
return cache.get(cls.KEY2) or cls.flush_adc_counter()
|
return cache.get(cls.KEY2) or cls.flush_adc_counter()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def flush_sub_counter(cls):
|
||||||
|
result = dict(type_id2users=dict())
|
||||||
|
|
||||||
|
types = db.session.query(PreferenceShowAttributes.type_id,
|
||||||
|
PreferenceShowAttributes.uid, PreferenceShowAttributes.created_at).filter(
|
||||||
|
PreferenceShowAttributes.deleted.is_(False)).group_by(
|
||||||
|
PreferenceShowAttributes.uid, PreferenceShowAttributes.type_id)
|
||||||
|
for i in types:
|
||||||
|
result['type_id2users'].setdefault(i.type_id, []).append(i.uid)
|
||||||
|
|
||||||
|
types = PreferenceTreeView.get_by(to_dict=False)
|
||||||
|
for i in types:
|
||||||
|
|
||||||
|
result['type_id2users'].setdefault(i.type_id, [])
|
||||||
|
if i.uid not in result['type_id2users'][i.type_id]:
|
||||||
|
result['type_id2users'][i.type_id].append(i.uid)
|
||||||
|
|
||||||
|
cache.set(cls.KEY3, result, timeout=0)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_sub_counter(cls):
|
||||||
|
return cache.get(cls.KEY3) or cls.flush_sub_counter()
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
# -*- coding:utf-8 -*-
|
# -*- coding:utf-8 -*-
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import toposort
|
import toposort
|
||||||
from flask import abort
|
from flask import abort
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
@ -46,6 +45,7 @@ from api.models.cmdb import CITypeRelation
|
||||||
from api.models.cmdb import CITypeTrigger
|
from api.models.cmdb import CITypeTrigger
|
||||||
from api.models.cmdb import CITypeUniqueConstraint
|
from api.models.cmdb import CITypeUniqueConstraint
|
||||||
from api.models.cmdb import CustomDashboard
|
from api.models.cmdb import CustomDashboard
|
||||||
|
from api.models.cmdb import PreferenceCITypeOrder
|
||||||
from api.models.cmdb import PreferenceRelationView
|
from api.models.cmdb import PreferenceRelationView
|
||||||
from api.models.cmdb import PreferenceSearchOption
|
from api.models.cmdb import PreferenceSearchOption
|
||||||
from api.models.cmdb import PreferenceShowAttributes
|
from api.models.cmdb import PreferenceShowAttributes
|
||||||
|
@ -75,12 +75,13 @@ class CITypeManager(object):
|
||||||
return CIType.get_by_id(ci_type.id)
|
return CIType.get_by_id(ci_type.id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_ci_types(type_name=None):
|
def get_ci_types(type_name=None, like=True):
|
||||||
resources = None
|
resources = None
|
||||||
if current_app.config.get('USE_ACL') and not is_app_admin('cmdb'):
|
if current_app.config.get('USE_ACL') and not is_app_admin('cmdb'):
|
||||||
resources = set([i.get('name') for i in ACLManager().get_resources(ResourceTypeEnum.CI_TYPE)])
|
resources = set([i.get('name') for i in ACLManager().get_resources(ResourceTypeEnum.CI_TYPE)])
|
||||||
|
|
||||||
ci_types = CIType.get_by() if type_name is None else CIType.get_by_like(name=type_name)
|
ci_types = CIType.get_by() if type_name is None else (
|
||||||
|
CIType.get_by_like(name=type_name) if like else CIType.get_by(name=type_name))
|
||||||
res = list()
|
res = list()
|
||||||
for type_dict in ci_types:
|
for type_dict in ci_types:
|
||||||
attr = AttributeCache.get(type_dict["unique_id"])
|
attr = AttributeCache.get(type_dict["unique_id"])
|
||||||
|
@ -222,7 +223,7 @@ class CITypeManager(object):
|
||||||
|
|
||||||
for table in [PreferenceTreeView, PreferenceShowAttributes, PreferenceSearchOption, CustomDashboard,
|
for table in [PreferenceTreeView, PreferenceShowAttributes, PreferenceSearchOption, CustomDashboard,
|
||||||
CITypeGroupItem, CITypeAttributeGroup, CITypeAttribute, CITypeUniqueConstraint, CITypeTrigger,
|
CITypeGroupItem, CITypeAttributeGroup, CITypeAttribute, CITypeUniqueConstraint, CITypeTrigger,
|
||||||
AutoDiscoveryCIType, CIFilterPerms]:
|
AutoDiscoveryCIType, CIFilterPerms, PreferenceCITypeOrder]:
|
||||||
for item in table.get_by(type_id=type_id, to_dict=False):
|
for item in table.get_by(type_id=type_id, to_dict=False):
|
||||||
item.soft_delete(commit=False)
|
item.soft_delete(commit=False)
|
||||||
|
|
||||||
|
@ -1274,7 +1275,7 @@ class CITypeTemplateManager(object):
|
||||||
from api.lib.common_setting.upload_file import CommonFileCRUD
|
from api.lib.common_setting.upload_file import CommonFileCRUD
|
||||||
|
|
||||||
tpt = dict(
|
tpt = dict(
|
||||||
ci_types=CITypeManager.get_ci_types(type_name=ci_type.name),
|
ci_types=CITypeManager.get_ci_types(type_name=ci_type.name, like=False),
|
||||||
ci_type_auto_discovery_rules=list(),
|
ci_type_auto_discovery_rules=list(),
|
||||||
type2attributes=dict(),
|
type2attributes=dict(),
|
||||||
type2attribute_group=dict(),
|
type2attribute_group=dict(),
|
||||||
|
|
|
@ -114,6 +114,8 @@ class CIFilterPermsCRUD(DBMixin):
|
||||||
|
|
||||||
obj.soft_delete()
|
obj.soft_delete()
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not kwargs.get('ci_filter') and not kwargs.get('attr_filter'):
|
if not kwargs.get('ci_filter') and not kwargs.get('attr_filter'):
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import toposort
|
import toposort
|
||||||
from flask import abort
|
from flask import abort
|
||||||
|
@ -14,6 +13,7 @@ from api.lib.cmdb.attribute import AttributeManager
|
||||||
from api.lib.cmdb.cache import AttributeCache
|
from api.lib.cmdb.cache import AttributeCache
|
||||||
from api.lib.cmdb.cache import CITypeAttributesCache
|
from api.lib.cmdb.cache import CITypeAttributesCache
|
||||||
from api.lib.cmdb.cache import CITypeCache
|
from api.lib.cmdb.cache import CITypeCache
|
||||||
|
from api.lib.cmdb.cache import CMDBCounterCache
|
||||||
from api.lib.cmdb.const import ConstraintEnum
|
from api.lib.cmdb.const import ConstraintEnum
|
||||||
from api.lib.cmdb.const import PermEnum
|
from api.lib.cmdb.const import PermEnum
|
||||||
from api.lib.cmdb.const import ResourceTypeEnum
|
from api.lib.cmdb.const import ResourceTypeEnum
|
||||||
|
@ -24,6 +24,7 @@ from api.lib.exception import AbortException
|
||||||
from api.lib.perm.acl.acl import ACLManager
|
from api.lib.perm.acl.acl import ACLManager
|
||||||
from api.models.cmdb import CITypeAttribute
|
from api.models.cmdb import CITypeAttribute
|
||||||
from api.models.cmdb import CITypeRelation
|
from api.models.cmdb import CITypeRelation
|
||||||
|
from api.models.cmdb import PreferenceCITypeOrder
|
||||||
from api.models.cmdb import PreferenceRelationView
|
from api.models.cmdb import PreferenceRelationView
|
||||||
from api.models.cmdb import PreferenceSearchOption
|
from api.models.cmdb import PreferenceSearchOption
|
||||||
from api.models.cmdb import PreferenceShowAttributes
|
from api.models.cmdb import PreferenceShowAttributes
|
||||||
|
@ -38,13 +39,22 @@ class PreferenceManager(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_types(instance=False, tree=False):
|
def get_types(instance=False, tree=False):
|
||||||
|
ci_type_order = sorted(PreferenceCITypeOrder.get_by(uid=current_user.uid, to_dict=False), key=lambda x: x.order)
|
||||||
|
|
||||||
types = db.session.query(PreferenceShowAttributes.type_id).filter(
|
types = db.session.query(PreferenceShowAttributes.type_id).filter(
|
||||||
PreferenceShowAttributes.uid == current_user.uid).filter(
|
PreferenceShowAttributes.uid == current_user.uid).filter(
|
||||||
PreferenceShowAttributes.deleted.is_(False)).group_by(
|
PreferenceShowAttributes.deleted.is_(False)).group_by(
|
||||||
PreferenceShowAttributes.type_id).all() if instance else []
|
PreferenceShowAttributes.type_id).all() if instance else []
|
||||||
|
types = sorted(types, key=lambda x: {i.type_id: idx for idx, i in enumerate(
|
||||||
|
ci_type_order) if not i.is_tree}.get(x.type_id, 1))
|
||||||
|
|
||||||
tree_types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False) if tree else []
|
tree_types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False) if tree else []
|
||||||
type_ids = set([i.type_id for i in types + tree_types])
|
tree_types = sorted(tree_types, key=lambda x: {i.type_id: idx for idx, i in enumerate(
|
||||||
|
ci_type_order) if i.is_tree}.get(x.type_id, 1))
|
||||||
|
|
||||||
|
type_ids = [i.type_id for i in types + tree_types]
|
||||||
|
if types and tree_types:
|
||||||
|
type_ids = set(type_ids)
|
||||||
|
|
||||||
return [CITypeCache.get(type_id).to_dict() for type_id in type_ids]
|
return [CITypeCache.get(type_id).to_dict() for type_id in type_ids]
|
||||||
|
|
||||||
|
@ -59,32 +69,36 @@ class PreferenceManager(object):
|
||||||
:param tree:
|
:param tree:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
result = dict(self=dict(instance=[], tree=[], type_id2subs_time=dict()),
|
result = dict(self=dict(instance=[], tree=[], type_id2subs_time=dict()))
|
||||||
type_id2users=dict())
|
|
||||||
|
result.update(CMDBCounterCache.get_sub_counter())
|
||||||
|
|
||||||
|
ci_type_order = sorted(PreferenceCITypeOrder.get_by(uid=current_user.uid, to_dict=False), key=lambda x: x.order)
|
||||||
if instance:
|
if instance:
|
||||||
types = db.session.query(PreferenceShowAttributes.type_id,
|
types = db.session.query(PreferenceShowAttributes.type_id,
|
||||||
PreferenceShowAttributes.uid, PreferenceShowAttributes.created_at).filter(
|
PreferenceShowAttributes.uid, PreferenceShowAttributes.created_at).filter(
|
||||||
PreferenceShowAttributes.deleted.is_(False)).group_by(
|
PreferenceShowAttributes.deleted.is_(False)).filter(
|
||||||
|
PreferenceShowAttributes.uid == current_user.uid).group_by(
|
||||||
PreferenceShowAttributes.uid, PreferenceShowAttributes.type_id)
|
PreferenceShowAttributes.uid, PreferenceShowAttributes.type_id)
|
||||||
for i in types:
|
for i in types:
|
||||||
if i.uid == current_user.uid:
|
|
||||||
result['self']['instance'].append(i.type_id)
|
result['self']['instance'].append(i.type_id)
|
||||||
if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")):
|
if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")):
|
||||||
result['self']['type_id2subs_time'][i.type_id] = i.created_at
|
result['self']['type_id2subs_time'][i.type_id] = i.created_at
|
||||||
|
|
||||||
result['type_id2users'].setdefault(i.type_id, []).append(i.uid)
|
instance_order = [i.type_id for i in ci_type_order if not i.is_tree]
|
||||||
|
if len(instance_order) == len(result['self']['instance']):
|
||||||
|
result['self']['instance'] = instance_order
|
||||||
|
|
||||||
if tree:
|
if tree:
|
||||||
types = PreferenceTreeView.get_by(to_dict=False)
|
types = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=False)
|
||||||
for i in types:
|
for i in types:
|
||||||
if i.uid == current_user.uid:
|
|
||||||
result['self']['tree'].append(i.type_id)
|
result['self']['tree'].append(i.type_id)
|
||||||
if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")):
|
if str(i.created_at) > str(result['self']['type_id2subs_time'].get(i.type_id, "")):
|
||||||
result['self']['type_id2subs_time'][i.type_id] = i.created_at
|
result['self']['type_id2subs_time'][i.type_id] = i.created_at
|
||||||
|
|
||||||
result['type_id2users'].setdefault(i.type_id, [])
|
tree_order = [i.type_id for i in ci_type_order if i.is_tree]
|
||||||
if i.uid not in result['type_id2users'][i.type_id]:
|
if len(tree_order) == len(result['self']['tree']):
|
||||||
result['type_id2users'][i.type_id].append(i.uid)
|
result['self']['tree'] = tree_order
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -151,9 +165,22 @@ class PreferenceManager(object):
|
||||||
if i.attr_id not in attr_dict:
|
if i.attr_id not in attr_dict:
|
||||||
i.soft_delete()
|
i.soft_delete()
|
||||||
|
|
||||||
|
if not existed_all and attr_order:
|
||||||
|
cls.add_ci_type_order_item(type_id, is_tree=False)
|
||||||
|
|
||||||
|
elif not PreferenceShowAttributes.get_by(type_id=type_id, uid=current_user.uid, to_dict=False):
|
||||||
|
cls.delete_ci_type_order_item(type_id, is_tree=False)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_tree_view():
|
def get_tree_view():
|
||||||
|
ci_type_order = sorted(PreferenceCITypeOrder.get_by(uid=current_user.uid, is_tree=True, to_dict=False),
|
||||||
|
key=lambda x: x.order)
|
||||||
|
|
||||||
res = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=True)
|
res = PreferenceTreeView.get_by(uid=current_user.uid, to_dict=True)
|
||||||
|
if ci_type_order:
|
||||||
|
res = sorted(res, key=lambda x: {ii.type_id: idx for idx, ii in enumerate(
|
||||||
|
ci_type_order)}.get(x['type_id'], 1))
|
||||||
|
|
||||||
for item in res:
|
for item in res:
|
||||||
if item["levels"]:
|
if item["levels"]:
|
||||||
ci_type = CITypeCache.get(item['type_id']).to_dict()
|
ci_type = CITypeCache.get(item['type_id']).to_dict()
|
||||||
|
@ -172,8 +199,8 @@ class PreferenceManager(object):
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def create_or_update_tree_view(type_id, levels):
|
def create_or_update_tree_view(cls, type_id, levels):
|
||||||
attrs = CITypeAttributesCache.get(type_id)
|
attrs = CITypeAttributesCache.get(type_id)
|
||||||
for idx, i in enumerate(levels):
|
for idx, i in enumerate(levels):
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
|
@ -185,9 +212,12 @@ class PreferenceManager(object):
|
||||||
if existed is not None:
|
if existed is not None:
|
||||||
if not levels:
|
if not levels:
|
||||||
existed.soft_delete()
|
existed.soft_delete()
|
||||||
|
cls.delete_ci_type_order_item(type_id, is_tree=True)
|
||||||
return existed
|
return existed
|
||||||
return existed.update(levels=levels)
|
return existed.update(levels=levels)
|
||||||
elif levels:
|
elif levels:
|
||||||
|
cls.add_ci_type_order_item(type_id, is_tree=True)
|
||||||
|
|
||||||
return PreferenceTreeView.create(levels=levels, type_id=type_id, uid=current_user.uid)
|
return PreferenceTreeView.create(levels=levels, type_id=type_id, uid=current_user.uid)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -356,6 +386,9 @@ class PreferenceManager(object):
|
||||||
for i in PreferenceTreeView.get_by(type_id=type_id, uid=uid, to_dict=False):
|
for i in PreferenceTreeView.get_by(type_id=type_id, uid=uid, to_dict=False):
|
||||||
i.soft_delete()
|
i.soft_delete()
|
||||||
|
|
||||||
|
for i in PreferenceCITypeOrder.get_by(type_id=type_id, uid=uid, to_dict=False):
|
||||||
|
i.soft_delete()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_edit_relation(parent_id, child_id):
|
def can_edit_relation(parent_id, child_id):
|
||||||
views = PreferenceRelationView.get_by(to_dict=False)
|
views = PreferenceRelationView.get_by(to_dict=False)
|
||||||
|
@ -381,3 +414,36 @@ class PreferenceManager(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def add_ci_type_order_item(type_id, is_tree=False):
|
||||||
|
max_order = PreferenceCITypeOrder.get_by(
|
||||||
|
uid=current_user.uid, is_tree=is_tree, only_query=True).order_by(PreferenceCITypeOrder.order.desc()).first()
|
||||||
|
order = (max_order and max_order.order + 1) or 1
|
||||||
|
|
||||||
|
PreferenceCITypeOrder.create(type_id=type_id, is_tree=is_tree, uid=current_user.uid, order=order)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete_ci_type_order_item(type_id, is_tree=False):
|
||||||
|
existed = PreferenceCITypeOrder.get_by(uid=current_user.uid, type_id=type_id, is_tree=is_tree,
|
||||||
|
first=True, to_dict=False)
|
||||||
|
|
||||||
|
existed and existed.soft_delete()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def upsert_ci_type_order(type_ids, is_tree=False):
|
||||||
|
for idx, type_id in enumerate(type_ids):
|
||||||
|
order = idx + 1
|
||||||
|
existed = PreferenceCITypeOrder.get_by(uid=current_user.uid, type_id=type_id, is_tree=is_tree,
|
||||||
|
to_dict=False, first=True)
|
||||||
|
if existed is not None:
|
||||||
|
existed.update(order=order, flush=True)
|
||||||
|
else:
|
||||||
|
PreferenceCITypeOrder.create(uid=current_user.uid, type_id=type_id, is_tree=is_tree, order=order,
|
||||||
|
flush=True)
|
||||||
|
try:
|
||||||
|
db.session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
current_app.logger.error("upsert citype order failed: {}".format(e))
|
||||||
|
return abort(400, ErrFormat.unknown_error)
|
||||||
|
|
|
@ -465,16 +465,16 @@ class CITypeGrantView(APIView):
|
||||||
|
|
||||||
acl.grant_resource_to_role_by_rid(type_name, rid, ResourceTypeEnum.CI_TYPE, perms, rebuild=False)
|
acl.grant_resource_to_role_by_rid(type_name, rid, ResourceTypeEnum.CI_TYPE, perms, rebuild=False)
|
||||||
|
|
||||||
|
resource = None
|
||||||
if 'ci_filter' in request.values or 'attr_filter' in request.values:
|
if 'ci_filter' in request.values or 'attr_filter' in request.values:
|
||||||
CIFilterPermsCRUD().add(type_id=type_id, rid=rid, **request.values)
|
resource = CIFilterPermsCRUD().add(type_id=type_id, rid=rid, **request.values)
|
||||||
else:
|
|
||||||
|
if not resource:
|
||||||
from api.tasks.acl import role_rebuild
|
from api.tasks.acl import role_rebuild
|
||||||
from api.lib.perm.acl.const import ACL_QUEUE
|
from api.lib.perm.acl.const import ACL_QUEUE
|
||||||
|
|
||||||
app_id = AppCache.get('cmdb').id
|
app_id = AppCache.get('cmdb').id
|
||||||
current_app.logger.info((rid, app_id))
|
|
||||||
role_rebuild.apply_async(args=(rid, app_id), queue=ACL_QUEUE)
|
role_rebuild.apply_async(args=(rid, app_id), queue=ACL_QUEUE)
|
||||||
current_app.logger.info('done')
|
|
||||||
|
|
||||||
return self.jsonify(code=200)
|
return self.jsonify(code=200)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
|
|
||||||
from flask import abort
|
from flask import abort
|
||||||
|
from flask import current_app
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from api.lib.cmdb.ci_type import CITypeManager
|
from api.lib.cmdb.ci_type import CITypeManager
|
||||||
|
@ -187,3 +188,15 @@ class PreferenceRelationRevokeView(APIView):
|
||||||
acl.revoke_resource_from_role_by_rid(name, rid, ResourceTypeEnum.RELATION_VIEW, perms)
|
acl.revoke_resource_from_role_by_rid(name, rid, ResourceTypeEnum.RELATION_VIEW, perms)
|
||||||
|
|
||||||
return self.jsonify(code=200)
|
return self.jsonify(code=200)
|
||||||
|
|
||||||
|
|
||||||
|
class PreferenceCITypeOrderView(APIView):
|
||||||
|
url_prefix = ("/preference/ci_types/order",)
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
type_ids = request.values.get("type_ids")
|
||||||
|
is_tree = request.values.get("is_tree") in current_app.config.get('BOOL_TRUE')
|
||||||
|
|
||||||
|
PreferenceManager.upsert_ci_type_order(type_ids, is_tree)
|
||||||
|
|
||||||
|
return self.jsonify(type_ids=type_ids, is_tree=is_tree)
|
||||||
|
|
Loading…
Reference in New Issue