Coverage for control/typ/related.py : 86%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Types of values in related tables."""
3from bson.objectid import ObjectId
5from config import Config as C, Names as N
6from control.utils import pick as G, E
7from control.html import HtmlElements as H
8from control.typ.base import TypeBase
11CT = C.tables
12CW = C.web
14Qq = H.icon(CW.unknown[N.generic], asChar=True)
15QQ = H.icon(CW.unknown[N.generic])
17ACTUAL_TABLES = set(CT.actualTables)
20def castObjectId(value):
21 """Try to cast the value as an ObjectId.
22 Paramaters
23 ----------
24 value:string
25 The value to cast, normally a string representation of a BSON object id.
27 Returns
28 -------
29 objectId | None
30 The corresponding BSON object id if the input is a valid representation of
31 such an id, otherwise `None`.
32 """
34 try:
35 oValue = ObjectId(value)
36 except Exception:
37 oValue = None
38 return oValue
41class Related(TypeBase):
42 """Base class for types with values in other tables."""
44 needsContext = True
46 def __init__(self, context):
47 """## Initialization
49 Parameters
50 ----------
51 context: object
52 See below.
53 """
55 self.context = context
56 """*object* A `control.context.Context` singleton.
57 """
59 def normalize(self, strVal):
60 return strVal
62 def toDisplay(self, val, markup=True):
63 result = self.title(eid=val, markup=markup)
64 return result[1] if markup else result
66 def titleStr(self, record, markup=True, **kwargs):
67 valBare = (
68 G(record, N.title) or G(record, N.rep) or (E if markup is None else Qq)
69 )
70 return valBare if markup is None else H.he(valBare)
72 def titleHint(self, record):
73 return None
75 def title(self, record=None, eid=None, markup=False, active=None, **kwargs):
76 """Generate a title for a related record.
78 Parameters
79 ----------
80 record: dict, optional `None`
81 The record for which to generate a title.
82 eid: ObjectId, optional `None`
83 If `record` is not passed, use this to retrieve the full record.
84 markup: boolean
85 If true, generate the title in HTML markup, otherwise as a plain string.
86 active: ObjectId, optional `None`
87 If passed, is is the id of the currently *active* record, the one
88 that the current user is interacting with.
90 Returns
91 -------
92 string(html)
93 """
95 if record is None and eid is None: 95 ↛ 96line 95 didn't jump to line 96, because the condition on line 95 was never true
96 return None if markup is None else (QQ, QQ) if markup else Qq
98 table = self.name
100 if record is None:
101 context = self.context
102 record = context.getItem(table, eid)
104 titleStr = self.titleStr(record, markup=markup, **kwargs)
105 titleHint = self.titleHint(record)
107 if markup:
108 if eid is None: 108 ↛ 109line 108 didn't jump to line 109, because the condition on line 108 was never true
109 eid = G(record, N._id)
111 inActualCls = self.inActualCls(record)
112 atts = dict(cls=f"tag medium {inActualCls}")
113 if titleHint: 113 ↛ 114line 113 didn't jump to line 114, because the condition on line 113 was never true
114 atts[N.title] = titleHint
116 href = f"""/{table}/item/{eid}"""
117 titleFormatted = H.a(titleStr, href, target=N._blank, **atts)
118 return (titleStr, titleFormatted)
119 else:
120 return titleStr
122 def inActualCls(self, record):
123 """Get a CSS class name for a record based on whether it is *actual*.
125 Actual records belong to the current `package`, a record that specifies
126 which contribution types, and criteria are currently part of the workflow.
128 Parameters
129 ----------
130 record: dict
132 Returns
133 -------
134 string
135 `inactual` if the record is not actual, else the empty string.
136 """
138 table = self.name
140 isActual = (
141 table not in ACTUAL_TABLES
142 or not record
143 or G(record, N.actual, default=False)
144 )
145 return E if isActual else "inactual"