django-bom 1.258__py3-none-any.whl → 1.265__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,63 +6,223 @@
6
6
  {% block head-title %}{{ title }}{% endblock %}
7
7
 
8
8
  {% block content %}
9
- <div class="row container-app">
10
- <div class="col s12 l8 offset-l2">
11
- <ul id="tabs" class="tabs tabs-fixed-width">
12
- <li class="tab"><a id="user-tab" href="#user">User</a></li>
13
- <li class="tab"><a id="indabom-tab" href="#indabom">IndaBOM</a></li>
14
- <li class="tab"><a id="organization-tab" href="#organization">Organization</a></li>
15
- </ul>
9
+ <div class="container-app settings-grid row">
10
+ <div class="col s12 m3 l2 settings-nav">
11
+ <div class="collection">
12
+ <a href="#user" class="collection-item primary-color" id="user-nav">
13
+ <i class="material-icons">person</i>User
14
+ </a>
15
+ <a href="#organization" class="collection-item" id="organization-nav">
16
+ <i class="material-icons">business</i>Organization
17
+ </a>
18
+ <a href="#users" class="collection-item" id="users-nav">
19
+ <i class="material-icons">group</i>Members
20
+ </a>
21
+ <a href="#part-classes" class="collection-item" id="part-classes-nav">
22
+ <i class="material-icons">category</i>Part Classes
23
+ </a>
24
+ <a href="#property-definitions" class="collection-item" id="property-definitions-nav">
25
+ <i class="material-icons">list_alt</i>Property Definitions
26
+ </a>
27
+ <a href="#units" class="collection-item" id="units-nav">
28
+ <i class="material-icons">straighten</i>Units & Quantities
29
+ </a>
30
+ <a href="#part-number" class="collection-item" id="part-number-nav">
31
+ <i class="material-icons">format_list_numbered</i>Part Numbers
32
+ </a>
33
+ <a href="#integrations" class="collection-item" id="integrations-nav">
34
+ <i class="material-icons">integration_instructions</i>Integrations
35
+ </a>
36
+ </div>
16
37
  </div>
17
38
 
18
- <div id="user" class="col l8 offset-l2 s12">
19
- <div class="section">
20
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">person</i>User</h4>
21
- <form name="seller" action="{% url 'bom:settings' tab_anchor=USER_TAB %}" method="post">
22
- {% csrf_token %}
23
- <div class="row">
24
- <div class="col s12">
25
- <p>Your role is: <b>{{ user.bom_profile.get_role_display }}</b></p>
26
- <p>Your username is: <b>{{ user.username }}</b></p>
27
- <p>To request a change in role please contact <a
28
- href="mailto:{{ organization.owner.email }}">{{ organization.owner.email }}</a> for
29
- assistance.</p>
39
+ <div class="col s12 m9 l10 settings-content">
40
+ <div id="user" class="settings-section">
41
+ <div class="section">
42
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">person</i>User</h4>
43
+ <form name="seller" action="{% url 'bom:settings' tab_anchor='user' %}" method="post">
44
+ {% csrf_token %}
45
+ <div class="row">
46
+ <div class="col s12">
47
+ <p>Your role is: <b>{{ user.bom_profile.get_role_display }}</b></p>
48
+ <p>Your username is: <b>{{ user.username }}</b></p>
49
+ <p>To request a change in role please contact <a
50
+ href="mailto:{{ organization.owner.email }}">{{ organization.owner.email }}</a>
51
+ for
52
+ assistance.</p>
53
+ </div>
54
+ </div>
55
+ <div class="row">
56
+ {{ user_form.first_name|materializecss:'s12 l6' }}
57
+ {{ user_form.last_name|materializecss:'s12 l6' }}
58
+ {{ user_form.email|materializecss:'s12' }}
59
+ </div>
60
+ <div class="row">
61
+ <div class="col s12 right-align">
62
+ <button class="waves-effect waves-light btn btn-primary" type="submit"
63
+ name="submit-edit-user">
64
+ Save
65
+ </button>
66
+ </div>
30
67
  </div>
68
+ </form>
69
+ </div>
70
+
71
+ <div class="section" style="padding: 16px; border-radius: 6px;">
72
+ <h4 class="section-title red-text text-darken-2" style="margin-top:0;"><i
73
+ class="material-icons red-text text-darken-2">warning</i>Danger Zone</h4>
74
+ <p>Deleting your account is permanent. If you are the organization owner, your organization will
75
+ also be
76
+ deleted unless you transfer ownership before proceeding.</p>
77
+ <div class="right-align" style="margin-top: 8px;">
78
+ <a href="{% url 'account-delete' %}" class="btn red lighten-1">Delete My Account</a>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <div id="organization" class="settings-section">
84
+ {% if perms.bom.manage_members %}
85
+ <div class="section">
86
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">business</i>Organization
87
+ </h4>
88
+ <form name="seller" action="{% url 'bom:settings' tab_anchor='organization' %}" method="post"
89
+ enctype="multipart/form-data">
90
+ {% csrf_token %}
91
+ <div class="row">
92
+ {{ organization_form|materializecss:'s12' }}
93
+ </div>
94
+ <div class="row">
95
+ <div class="col s12 right-align">
96
+ <button class="waves-effect waves-light btn btn-primary" type="submit"
97
+ name="submit-edit-organization"
98
+ onclick="return confirm('Are you sure you want to change the organization information?')">
99
+ Save
100
+ </button>
101
+ </div>
102
+ </div>
103
+ </form>
31
104
  </div>
32
- <div class="row">
33
- {{ user_form.first_name|materializecss:'s12 l6' }}
34
- {{ user_form.last_name|materializecss:'s12 l6' }}
35
- {{ user_form.email|materializecss:'s12' }}
105
+
106
+ {% include 'bom/subscription_panel.html' %}
107
+
108
+ <div class="section">
109
+ <h4 class="section-title"><i class="material-icons red-text text-darken-1">exit_to_app</i>Leave
110
+ Your Organization</h4>
111
+ <p>Warning, the only way back in to {{ organization.name }} is if you are invited by an
112
+ organization administrator.</p>
113
+ <form name="leave-organization" action="{% url 'bom:settings' tab_anchor='organization' %}"
114
+ method="post" enctype="multipart/form-data">
115
+ {% csrf_token %}
116
+ <div class="right-align">
117
+ <button class="waves-effect waves-light btn red lighten-1" type="submit"
118
+ name="submit-leave-organization">
119
+ <i class="material-icons left">exit_to_app</i>Leave Organization
120
+ </button>
121
+ </div>
122
+ </form>
36
123
  </div>
37
- <div class="row">
38
- <div class="col s12 right-align">
39
- <button class="waves-effect waves-light btn btn-primary" type="submit"
40
- name="submit-edit-user">
41
- Save
42
- </button>
124
+ {% else %}
125
+ <div class="section">
126
+ <h4 class="section-title">Organization</h4>
127
+ <p>You are a member of <b>{{ organization.name }}</b>.</p>
128
+ <div class="section">
129
+ <h4 class="section-title"><i class="material-icons red-text text-darken-1">exit_to_app</i>Leave
130
+ Your Organization</h4>
131
+ <p>Warning, the only way back in to {{ organization.name }} is if you are invited by an
132
+ organization administrator.</p>
133
+ <form name="leave-organization" action="{% url 'bom:settings' tab_anchor='organization' %}"
134
+ method="post" enctype="multipart/form-data">
135
+ {% csrf_token %}
136
+ <div class="right-align">
137
+ <button class="waves-effect waves-light btn red lighten-1" type="submit"
138
+ name="submit-leave-organization">
139
+ <i class="material-icons left">exit_to_app</i>Leave Organization
140
+ </button>
141
+ </div>
142
+ </form>
43
143
  </div>
44
144
  </div>
45
- </form>
145
+ {% endif %}
46
146
  </div>
47
147
 
48
- <div class="section" style="padding: 16px; border-radius: 6px;">
49
- <h4 class="section-title red-text text-darken-2" style="margin-top:0;"><i
50
- class="material-icons red-text text-darken-2">warning</i>Danger Zone</h4>
51
- <p>Deleting your account is permanent. If you are the organization owner, your organization will also be
52
- deleted unless you transfer ownership before proceeding.</p>
53
- <div class="right-align" style="margin-top: 8px;">
54
- <a href="{% url 'account-delete' %}" class="btn red lighten-1">Delete My Account</a>
55
- </div>
148
+ <div id="users" class="settings-section">
149
+ {% if perms.bom.manage_members %}
150
+ <div class="section">
151
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">group</i>Organization
152
+ Members
153
+ </h4>
154
+ <form name="seller" action="{% url 'bom:settings' tab_anchor='organization' %}" method="post"
155
+ enctype="multipart/form-data">
156
+ {% csrf_token %}
157
+ <table>
158
+ <thead>
159
+ <tr>
160
+ <th class="text-normal"><label><input type="checkbox"
161
+ id="user-select-all"><span></span></label>
162
+ </th>
163
+ <th class="text-normal">Role</th>
164
+ <th class="text-normal">User Name</th>
165
+ <th class="text-normal">Full Name</th>
166
+ <th class="text-normal">Email</th>
167
+ <th class="text-normal"></th>
168
+ </tr>
169
+ </thead>
170
+ <tbody>
171
+ {% for org_user in users_in_organization %}
172
+ <tr>
173
+ <td>
174
+ {% if org_user != organization.owner %}
175
+ <label><input type="checkbox" class="filled-in"
176
+ name="remove_user_meta_id_{{ org_user.bom_profile.id }}"><span/></label>{% endif %}
177
+ </td>
178
+ <td class="text-normal">{% if org_user == organization.owner %}Owner{% else %}
179
+ {{ org_user.bom_profile.get_role_display }}{% endif %}</td>
180
+ <td class="text-normal">{{ org_user.username }}</td>
181
+ <td class="text-normal">{{ org_user.first_name }} {{ org_user.last_name }}</td>
182
+ <td class="text-normal"><a
183
+ href="mailto:{{ user.email }}">{{ org_user.email }}</a>
184
+ </td>
185
+ <td class="table-action right-align">
186
+ <a href="{% url 'bom:user-meta-edit' user_meta_id=org_user.bom_profile.id %}"><i
187
+ class="material-icons left">edit</i>Edit</a>
188
+ </td>
189
+ </tr>
190
+ {% empty %}
191
+ <tr>
192
+ <td colspan="5" style="font-style: italic;">There are no additional users in
193
+ this
194
+ organization.
195
+ </td>
196
+ </tr>
197
+ {% endfor %}
198
+ </tbody>
199
+ </table>
200
+ <div class="row" style="padding-top: 16px;">
201
+ <div class="col s6">
202
+ <button class="waves-effect waves-light btn red lighten-1" type="submit"
203
+ name="submit-remove-user"
204
+ onclick="return confirm('Are you sure you want to remove the selected users from {{ organization }}?')">
205
+ Remove Selected
206
+ </button>
207
+ </div>
208
+ <div class="col s6 right-align">
209
+ {% include 'bom/bom-modal-add-users.html' with modal_title='Add User' form=user_add_form action=user_add_form_action name='submit-add-user' %}
210
+ </div>
211
+ </div>
212
+ </form>
213
+ </div>
214
+ {% else %}
215
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
216
+ {% endif %}
56
217
  </div>
57
- </div>
58
218
 
59
- <div id="indabom" class="col s12 l8 offset-l2">
60
- {% if profile.role == 'A' %}
61
- {% if organization.number_scheme == 'S' %}
219
+ <div id="part-classes" class="settings-section">
220
+ {% if perms.bom.manage_members %}
62
221
  <div class="section">
63
222
  <h4 class="section-title"><i class="material-icons teal-text text-darken-1">category</i>Part
64
223
  Classes</h4>
65
- <form name="seller" action="{% url 'bom:settings' tab_anchor=INDABOM_TAB %}" method="post" enctype="multipart/form-data">
224
+ <form name="seller" action="{% url 'bom:settings' tab_anchor='indabom' %}" method="post"
225
+ enctype="multipart/form-data">
66
226
  {% csrf_token %}
67
227
  {% if part_classes.count > 0 %}
68
228
  <div class="row" style="margin-bottom: 0;">
@@ -141,399 +301,383 @@
141
301
  {% include 'bom/bom-form-modal.html' with modal_title='Add Part Class' form=part_class_form action=part_class_form_action name='submit-part-class-create' %}
142
302
  </div>
143
303
  </div>
144
-
145
- <div class="divider"></div>
304
+ {% else %}
305
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
146
306
  {% endif %}
307
+ </div>
147
308
 
148
- <div class="section">
149
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">list_alt</i>Property
150
- Definitions</h4>
151
- <p>Define part properties (e.g. Capacitance, Length, Sheen), their data type, and their
152
- associated quantity of measure.</p>
153
- {% if property_definitions.count > 0 %}
154
- <table class="striped tight">
155
- <thead>
156
- <tr>
157
- <th class="text-normal">Name</th>
158
- <th class="text-normal">Type</th>
159
- <th class="text-normal">Required</th>
160
- <th class="text-normal">Quantity of Measure</th>
161
- <th class="text-normal">Options</th>
162
- </tr>
163
- </thead>
164
- <tbody>
165
- {% for prop in property_definitions %}
309
+ <div id="property-definitions" class="settings-section">
310
+ {% if perms.bom.manage_members %}
311
+ <div class="section">
312
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">list_alt</i>Property
313
+ Definitions</h4>
314
+ <p>Define part properties (e.g. Capacitance, Length, Sheen), their data type, and their
315
+ associated quantity of measure.</p>
316
+ {% if property_definitions.count > 0 %}
317
+ <table class="striped tight">
318
+ <thead>
166
319
  <tr>
167
- <td class="text-normal">{{ prop.name }}</td>
168
- <td class="text-normal">{{ prop.get_type_display }}</td>
169
- <td class="text-normal">{% if prop.required %}Yes{% else %}No{% endif %}</td>
170
- <td class="text-normal">{{ prop.quantity_of_measure.name|default:"-" }}</td>
171
- <td>
172
- {% if prop.organization == organization %}
173
- <a class="table-action"
174
- href="{% url 'bom:property-definition-edit' property_definition_id=prop.id %}"><i
175
- class="material-icons left">edit</i>Edit</a>
176
- <a class="table-action red-text"
177
- href="{% url 'bom:property-definition-delete' property_definition_id=prop.id %}"
178
- onclick="return confirm('Are you sure you want to delete this property definition?')"><i
179
- class="material-icons left">delete</i></a>
180
- {% else %}
181
- <span class="table-action tooltipped grey-text d-flex-inline align-center"
182
- data-position="top"
183
- data-tooltip="System Default: Cannot be modified">
184
- <i class="material-icons left" style="font-size: 1.2rem;">lock</i> System
185
- </span>
186
- {% endif %}
187
- </td>
320
+ <th class="text-normal">Name</th>
321
+ <th class="text-normal">Type</th>
322
+ <th class="text-normal">Required</th>
323
+ <th class="text-normal">Quantity of Measure</th>
324
+ <th class="text-normal">Options</th>
188
325
  </tr>
189
- {% endfor %}
190
- </tbody>
191
- </table>
192
- {% else %}
193
- <p>No global property definitions defined.</p>
194
- {% endif %}
195
- <div class="right-align" style="margin-top: 16px;">
196
- <a href="{% url 'bom:property-definition-add' %}"
197
- class="waves-effect waves-light btn btn-primary">
198
- <i class="material-icons left">add</i>Add Property Definition
199
- </a>
326
+ </thead>
327
+ <tbody>
328
+ {% for prop in property_definitions %}
329
+ <tr>
330
+ <td class="text-normal">{{ prop.name }}</td>
331
+ <td class="text-normal">{{ prop.get_type_display }}</td>
332
+ <td class="text-normal">{% if prop.required %}Yes{% else %}No{% endif %}</td>
333
+ <td class="text-normal">{{ prop.quantity_of_measure.name|default:"-" }}</td>
334
+ <td>
335
+ {% if prop.organization == organization %}
336
+ <a class="table-action"
337
+ href="{% url 'bom:property-definition-edit' property_definition_id=prop.id %}"><i
338
+ class="material-icons left">edit</i>Edit</a>
339
+ <a class="table-action red-text"
340
+ href="{% url 'bom:property-definition-delete' property_definition_id=prop.id %}"
341
+ onclick="return confirm('Are you sure you want to delete this property definition?')"><i
342
+ class="material-icons left">delete</i></a>
343
+ {% else %}
344
+ <span class="table-action tooltipped grey-text d-flex-inline align-center"
345
+ data-position="top"
346
+ data-tooltip="System Default: Cannot be modified">
347
+ <i class="material-icons left" style="font-size: 1.2rem;">lock</i> System
348
+ </span>
349
+ {% endif %}
350
+ </td>
351
+ </tr>
352
+ {% endfor %}
353
+ </tbody>
354
+ </table>
355
+ {% else %}
356
+ <p>No global property definitions defined.</p>
357
+ {% endif %}
358
+ <div class="right-align" style="margin-top: 16px;">
359
+ <a href="{% url 'bom:property-definition-add' %}"
360
+ class="waves-effect waves-light btn btn-primary">
361
+ <i class="material-icons left">add</i>Add Property Definition
362
+ </a>
363
+ </div>
200
364
  </div>
201
- </div>
202
-
203
- <div class="divider"></div>
365
+ {% else %}
366
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
367
+ {% endif %}
368
+ </div>
204
369
 
205
- <div class="section">
206
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">straighten</i>Units &
207
- Quantities</h4>
208
- <p>Define quantities of measure (e.g. Length, Resistance) and their associated units (e.g. m, mm,
209
- Ohm, kOhm).</p>
210
- {% if quantities_of_measure.count > 0 %}
211
- <table class="striped tight">
212
- <thead>
213
- <tr>
214
- <th class="text-normal">Quantity</th>
215
- <th class="text-normal">Units</th>
216
- <th class="text-normal">Options</th>
217
- </tr>
218
- </thead>
219
- <tbody>
220
- {% for qom in quantities_of_measure %}
370
+ <div id="units" class="settings-section">
371
+ {% if perms.bom.manage_members %}
372
+ <div class="section">
373
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">straighten</i>Units
374
+ & Quantities</h4>
375
+ <p>Define quantities of measure (e.g. Length, Resistance) and their associated units (e.g. m,
376
+ mm, Ohm, kOhm).</p>
377
+ {% if quantities_of_measure.count > 0 %}
378
+ <table class="striped tight">
379
+ <thead>
221
380
  <tr>
222
- <td class="text-normal">{{ qom.name }}</td>
223
- <td class="text-normal">
224
- {% for unit in qom.units.all|slice:":3" %}
225
- {{ unit.symbol }}{% if not forloop.last %}, {% endif %}
226
- {% endfor %}
381
+ <th class="text-normal">Quantity</th>
382
+ <th class="text-normal">Units</th>
383
+ <th class="text-normal">Options</th>
384
+ </tr>
385
+ </thead>
386
+ <tbody>
387
+ {% for qom in quantities_of_measure %}
388
+ <tr>
389
+ <td class="text-normal">{{ qom.name }}</td>
390
+ <td class="text-normal">
391
+ {% for unit in qom.units.all|slice:":3" %}
392
+ {{ unit.symbol }}{% if not forloop.last %}, {% endif %}
393
+ {% endfor %}
227
394
 
228
- {% if qom.units.count > 3 %}
229
- <span class="grey-text text-darken-1 tooltipped"
230
- data-tooltip="
395
+ {% if qom.units.count > 3 %}
396
+ <span class="grey-text text-darken-1 tooltipped"
397
+ data-tooltip="
231
398
 
232
399
 
233
400
 
234
401
 
235
- {% for unit in qom.units.all %}{{ unit.name }}{% if not forloop.last %}, {% endif %}{% endfor %}">
236
- (+{{ qom.units.count|add:"-3" }} more)
237
- </span>
238
- {% endif %}
239
- </td>
240
- <td>
241
- {% if qom.organization == organization %}
242
- <a class="table-action"
243
- href="{% url 'bom:quantity-of-measure-edit' quantity_of_measure_id=qom.id %}"><i
244
- class="material-icons left">edit</i>Edit</a>
245
- <a class="table-action red-text"
246
- href="{% url 'bom:quantity-of-measure-delete' quantity_of_measure_id=qom.id %}"
247
- onclick="return confirm('Are you sure you want to delete this quantity of measure and all its units?')"><i
248
- class="material-icons left">delete</i></a>
249
- {% else %}
250
- <span class="table-action tooltipped grey-text d-flex-inline align-center"
251
- data-position="top"
252
- data-tooltip="System Default: Cannot be modified">
253
- <i class="material-icons left" style="font-size: 1.2rem;">lock</i> System
254
- </span>
255
- {% endif %}
256
- </td>
257
- </tr>
258
- {% endfor %}
259
- </tbody>
260
- </table>
261
- {% else %}
262
- <p>No quantities of measure defined.</p>
263
- {% endif %}
264
- <div class="right-align" style="margin-top: 16px;">
265
- <a href="{% url 'bom:quantity-of-measure-add' %}"
266
- class="waves-effect waves-light btn btn-primary">
267
- <i class="material-icons left">add</i>Add Quantity of Measure
268
- </a>
269
- </div>
270
- </div>
271
402
 
272
- {% if organization.number_scheme == 'S' %}
273
- <div class="divider"></div>
274
- <div class="section">
275
- <h4 class="section-title" id="indabom-part-number"><i
276
- class="material-icons teal-text text-darken-1">format_list_numbered</i>Part Number</h4>
277
- <form name="seller" action="{% url 'bom:settings' tab_anchor=INDABOM_TAB %}" method="post"
278
- enctype="multipart/form-data">
279
- {% csrf_token %}
280
- <p>You may only increase the number of digits for each component of the part number: the
281
- part class code (C), part item number (N), and the part variation (V).</p>
282
- <p>Your organization's current configuration is
283
- <b>{{ organization.number_cs }}-{{ organization.number_ns }}
284
- {% if organization.number_vs %}-{{ organization.number_vs }}{% endif %}</b></p>
285
- <div class="row">
286
- {{ organization_number_len_form|materializecss:'s4 l2' }}
287
- <div class="col s12 l6 input-field right-align">
288
- <button class="waves-effect waves-light btn btn-primary" type="submit"
289
- name="submit-number-item-len"
290
- onclick="return confirm('Are you sure you want to change the number of digits?')">
291
- Save
292
- </button>
293
- </div>
294
- </div>
295
- </form>
296
- </div>
297
- {% endif %}
298
403
 
299
- <div class="divider"></div>
300
404
 
301
- <div class="section">
302
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">swap_horiz</i>Change
303
- Organization Number Scheme</h4>
304
- <p>Your organization's number scheme is currently:
305
- <b>{{ organization.get_number_scheme_display }}</b></p>
306
- <ul class="browser-default">
307
- {% if organization.number_scheme == 'S' or organization_parts_count == 0 %}
308
- <li style="padding-bottom: 16px;"><b>Semi-intelligent</b> e.g. CCC-NNNN-YY<br>Consists of 3
309
- components: a 3-digit part class, a N-digit part number, and a 2-digit variation.
310
- IndaBOM part numbers are designed to be simple to assign and simple to subsequently
311
- write, type, or speak. You define the part classes in your organization, and how long
312
- your N-digit part number is below.
313
- </li>
314
- {% endif %}
315
- {% if organization.number_scheme == 'I' or organization_parts_count == 0 %}
316
- <li><b>Intelligent</b> You control your numbers.<br>Intelligent part numbering on IndaBOM
317
- allows the user to assign any part number to a part. The part number contains
318
- descriptive details embedded within that provides noteworthy information about the part.
319
- For example, a capacitor may be named C0402X5R33PF to indicate that it is a capacitor of
320
- size "0402", using a X5R dialectric, and is 33pF.
321
- </li>
322
- {% endif %}
323
- </ul>
324
- <p style="font-size: 15px;">You can read more about the options <a
325
- href="{% url 'bom:help' %}#part-numbering" target="_blank">here</a>.</p>
326
- {% if organization_parts_count > 0 %}
327
- <p><b>You've already created {{ organization_parts_count }}
328
- part{{ organization_parts_count|pluralize }}.</b> Since changing your organization number
329
- scheme requires changing your parts numbers, please manually delete your parts then come
330
- back here to change your organization number scheme. Alternatively we can help delete your
331
- parts if you reach out to info@indabom.com.</p>
332
- {% else %}
333
- <form name="number-scheme" action="{% url 'bom:settings' tab_anchor=INDABOM_TAB %}"
334
- method="post">
335
- {% csrf_token %}
336
- <button type="submit" name="change-number-scheme"
337
- class="waves-effect waves-light btn red lighten-1">Change Scheme to
338
- {% if organization.number_scheme == 'S' %}Intelligent{% else %}
339
- Semi-Intelligent{% endif %}</button>
340
- </form>
341
- {% endif %}
342
- </div>
343
- {% else %}
344
- {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
345
- {% endif %}
346
- </div>
347
405
 
348
- <div id="organization" class="col s12 l8 offset-l2">
349
- {% if user.bom_profile.role == 'A' %}
350
- <div class="section">
351
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">business</i>Organization
352
- </h4>
353
- <form name="seller" action="{% url 'bom:settings' tab_anchor=ORGANIZATION_TAB %}" method="post"
354
- enctype="multipart/form-data">
355
- {% csrf_token %}
356
- <div class="row">
357
- {{ organization_form|materializecss:'s12' }}
358
- </div>
359
- <div class="row">
360
- <div class="col s12 right-align">
361
- <button class="waves-effect waves-light btn btn-primary" type="submit"
362
- name="submit-edit-organization"
363
- onclick="return confirm('Are you sure you want to change the organization information?')">
364
- Save
365
- </button>
366
- </div>
367
- </div>
368
- </form>
369
- </div>
370
406
 
371
- {# Subscription & Billing placed after Users for a more natural flow #}
372
- {% include 'bom/subscription_panel.html' %}
373
407
 
374
- <div class="section">
375
- <h4 class="section-title"><i class="material-icons teal-text text-darken-1">group</i>Users</h4>
376
- <form name="seller" action="{% url 'bom:settings' tab_anchor=ORGANIZATION_TAB %}" method="post"
377
- enctype="multipart/form-data">
378
- {% csrf_token %}
379
- <table>
380
- <thead>
381
- <tr>
382
- <th class="text-normal"><label><input type="checkbox" id="user-select-all"><span></span></label>
383
- </th>
384
- <th class="text-normal">Role</th>
385
- <th class="text-normal">User Name</th>
386
- <th class="text-normal">Full Name</th>
387
- <th class="text-normal">Email</th>
388
- <th class="text-normal"></th>
389
- </tr>
390
- </thead>
391
- <tbody>
392
- {% for org_user in users_in_organization %}
393
- <tr>
394
- <td>
395
- {% if org_user != organization.owner %}
396
- <label><input type="checkbox" class="filled-in"
397
- name="remove_user_meta_id_{{ org_user.bom_profile.id }}"><span/></label>{% endif %}
398
- </td>
399
- <td class="text-normal">{% if org_user == organization.owner %}Owner{% else %}
400
- {{ org_user.bom_profile.get_role_display }}{% endif %}</td>
401
- <td class="text-normal">{{ org_user.username }}</td>
402
- <td class="text-normal">{{ org_user.first_name }} {{ org_user.last_name }}</td>
403
- <td class="text-normal"><a href="mailto:{{ user.email }}">{{ org_user.email }}</a>
404
- </td>
405
- <td class="table-action right-align">
406
- <a href="{% url 'bom:user-meta-edit' user_meta_id=org_user.bom_profile.id %}"><i
407
- class="material-icons left">edit</i>Edit</a>
408
- </td>
409
- </tr>
410
- {% empty %}
411
- <tr>
412
- <td colspan="5" style="font-style: italic;">There are no additional users in this
413
- organization.
414
- </td>
415
- </tr>
416
- {% endfor %}
417
- </tbody>
418
- </table>
419
- <div class="row" style="padding-top: 16px;">
420
- <div class="col s6">
421
- <button class="waves-effect waves-light btn red lighten-1" type="submit"
422
- name="submit-remove-user"
423
- onclick="return confirm('Are you sure you want to remove the selected users from {{ organization }}?')">
424
- Remove Selected
425
- </button>
426
- </div>
427
- <div class="col s6 right-align">
428
- {% include 'bom/bom-modal-add-users.html' with modal_title='Add User' form=user_add_form action=user_add_form_action name='submit-add-user' %}
429
- </div>
430
- </div>
431
- </form>
432
- </div>
433
408
 
434
- <div class="section">
435
- <h4 class="section-title"><i
436
- class="material-icons teal-text text-darken-1">integration_instructions</i>Integrations</h4>
437
- <div class="section">
438
- <h5 class="section-title"><img title="Via Google Drive"
439
- src="{% static 'bom/img/google_drive_logo.svg' %}">Part File
440
- Storage
441
- with Google Drive</h5>
442
- {% if not google_authentication %}
443
- <p>Connect your Google account to access Google Drive features.
444
- {% if not organization.google_drive_parent %}Organization owners can enable file storage
445
- using Google Drive. {% if organization.owner == user %}Since you are the owner, you
446
- are
447
- able to enable file storage!{% else %}Contact your organization owner to enable.
448
- {% endif %}{% endif %}</p>
449
- <p>When you connect, we will create a folder called <b>IndaBOM Part Files</b> in your root
450
- of
451
- Google Drive (and it can be moved anywhere in your drive). To add files to a part,
452
- navigate
453
- to the part in IndaBOM, and on the part's <b>Specifications</b> tab, click the <img
454
- title="Via Google Drive" style="width: 16px; vertical-align: middle;"
455
- src="{% static 'bom/img/google_drive_logo.svg' %}"> Google Drive link. This will
456
- create a folder for your part in your root IndaBOM directory, or take you there if it
457
- already exists.</p>
458
- <p>You'll be able to access the files directly through Google Drive, and through
459
- IndaBOM.</p>
409
+
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+ {% for unit in qom.units.all %}{{ unit.name }}{% if not forloop.last %}, {% endif %}{% endfor %}">
424
+ (+{{ qom.units.count|add:"-3" }} more)
425
+ </span>
426
+ {% endif %}
427
+ </td>
428
+ <td>
429
+ {% if qom.organization == organization %}
430
+ <a class="table-action"
431
+ href="{% url 'bom:quantity-of-measure-edit' quantity_of_measure_id=qom.id %}"><i
432
+ class="material-icons left">edit</i>Edit</a>
433
+ <a class="table-action red-text"
434
+ href="{% url 'bom:quantity-of-measure-delete' quantity_of_measure_id=qom.id %}"
435
+ onclick="return confirm('Are you sure you want to delete this quantity of measure and all its units?')"><i
436
+ class="material-icons left">delete</i></a>
437
+ {% else %}
438
+ <span class="table-action tooltipped grey-text d-flex-inline align-center"
439
+ data-position="top"
440
+ data-tooltip="System Default: Cannot be modified">
441
+ <i class="material-icons left" style="font-size: 1.2rem;">lock</i> System
442
+ </span>
443
+ {% endif %}
444
+ </td>
445
+ </tr>
446
+ {% endfor %}
447
+ </tbody>
448
+ </table>
460
449
  {% else %}
461
- <p>You're connected with Google and can access Google Drive features.</p>
450
+ <p>No quantities of measure defined.</p>
462
451
  {% endif %}
463
- <div>
464
- {% if google_authentication %}
465
- <p>Logged in to Google as: {{ google_authentication.uid }}</p>
466
- <div class="right-align">
467
- <form action="{% url 'social:disconnect' 'google-oauth2' %}" method="post">
468
- {% csrf_token %}
469
- <button class="waves-effect waves-light btn btn-primary" type="submit">
470
- Disconnect
452
+ <div class="right-align" style="margin-top: 16px;">
453
+ <a href="{% url 'bom:quantity-of-measure-add' %}"
454
+ class="waves-effect waves-light btn btn-primary">
455
+ <i class="material-icons left">add</i>Add Quantity of Measure
456
+ </a>
457
+ </div>
458
+ </div>
459
+ {% else %}
460
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
461
+ {% endif %}
462
+ </div>
463
+
464
+ <div id="part-number" class="settings-section">
465
+ {% if perms.bom.manage_members %}
466
+ <div class="section">
467
+ <h4 class="section-title" id="indabom-part-number-header"><i
468
+ class="material-icons teal-text text-darken-1">format_list_numbered</i>Part Number</h4>
469
+ {% if organization.number_scheme == 'S' %}
470
+ <form name="seller" action="{% url 'bom:settings' tab_anchor='indabom' %}" method="post"
471
+ enctype="multipart/form-data">
472
+ {% csrf_token %}
473
+ <p>You may only increase the number of digits for each component of the part number: the
474
+ part class code (C), part item number (N), and the part variation (V).</p>
475
+ <p>Your organization's current configuration is
476
+ <b>{{ organization.number_cs }}-{{ organization.number_ns }}
477
+ {% if organization.number_vs %}-{{ organization.number_vs }}{% endif %}</b></p>
478
+ <div class="row">
479
+ {{ organization_number_len_form|materializecss:'s4 l2' }}
480
+ <div class="col s12 l6 input-field right-align">
481
+ <button class="waves-effect waves-light btn btn-primary" type="submit"
482
+ name="submit-number-item-len"
483
+ onclick="return confirm('Are you sure you want to change the number of digits?')">
484
+ Save
471
485
  </button>
472
- </form>
486
+ </div>
473
487
  </div>
488
+ </form>
489
+ <div class="divider"></div>
490
+ {% endif %}
491
+
492
+ <div class="section">
493
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">swap_horiz</i>Change
494
+ Organization Number Scheme</h4>
495
+ <p>Your organization's number scheme is currently:
496
+ <b>{{ organization.get_number_scheme_display }}</b></p>
497
+ <ul class="browser-default">
498
+ {% if organization.number_scheme == 'S' or organization_parts_count == 0 %}
499
+ <li style="padding-bottom: 16px;"><b>Semi-intelligent</b> e.g. CCC-NNNN-YY<br>Consists
500
+ of 3
501
+ components: a 3-digit part class, a N-digit part number, and a 2-digit
502
+ variation.
503
+ IndaBOM part numbers are designed to be simple to assign and simple to
504
+ subsequently
505
+ write, type, or speak. You define the part classes in your organization, and how
506
+ long
507
+ your N-digit part number is below.
508
+ </li>
509
+ {% endif %}
510
+ {% if organization.number_scheme == 'I' or organization_parts_count == 0 %}
511
+ <li><b>Intelligent</b> You control your numbers.<br>Intelligent part numbering on
512
+ IndaBOM
513
+ allows the user to assign any part number to a part. The part number contains
514
+ descriptive details embedded within that provides noteworthy information about
515
+ the part.
516
+ For example, a capacitor may be named C0402X5R33PF to indicate that it is a
517
+ capacitor of
518
+ size "0402", using a X5R dialectric, and is 33pF.
519
+ </li>
520
+ {% endif %}
521
+ </ul>
522
+ <p style="font-size: 15px;">You can read more about the options <a
523
+ href="{% url 'bom:help' %}#part-numbering" target="_blank">here</a>.</p>
524
+ {% if organization_parts_count > 0 %}
525
+ <p><b>You've already created {{ organization_parts_count }}
526
+ part{{ organization_parts_count|pluralize }}.</b> Since changing your organization
527
+ number
528
+ scheme requires changing your parts numbers, please manually delete your parts then
529
+ come
530
+ back here to change your organization number scheme. Alternatively we can help
531
+ delete your
532
+ parts if you reach out to info@indabom.com.</p>
474
533
  {% else %}
475
- <p>To get started, sign in with Google:</p>
476
- <div class="right-align">
477
- <a href="{% url "social:begin" "google-oauth2" %}">
478
- <img title="Google sign-in."
479
- src="{% static 'bom/img/google/web/1x/btn_google_signin_dark_normal_web.png' %}">
480
- </a>
481
- </div>
534
+ <form name="number-scheme" action="{% url 'bom:settings' tab_anchor='indabom' %}"
535
+ method="post">
536
+ {% csrf_token %}
537
+ <button type="submit" name="change-number-scheme"
538
+ class="waves-effect waves-light btn red lighten-1">Change Scheme to
539
+ {% if organization.number_scheme == 'S' %}Intelligent{% else %}
540
+ Semi-Intelligent{% endif %}</button>
541
+ </form>
482
542
  {% endif %}
483
543
  </div>
484
544
  </div>
485
- <div class="section">
486
- <h5 class="section-title"><img title="Sourcing via Mouser.com"
487
- src="{% static 'bom/img/mouser.png' %}">Automagic Sourcing via
488
- Mouser
489
- </h5>
490
- <!--<p>No connection required. To enable sourcing via Mouser, select which part classes you'd like
491
- enabled on the Settings IndaBOM tab. Once enabled, sourcing information will appear on part
492
- detail pages in which there are parts sourced via Mouser.</p>-->
493
- <p>Currently under construction.</p>
494
- </div>
495
- </div>
496
- {% endif %}
545
+ {% else %}
546
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
547
+ {% endif %}
548
+ </div>
497
549
 
498
- {% if profile.organization %}
499
- <div class="section">
500
- <h4 class="section-title"><i class="material-icons red-text text-darken-1">exit_to_app</i>Leave Your
501
- Organization</h4>
502
- <p>Warning, the only way back in to {{ organization.name }} is if you are invited by an organization
503
- administrator.</p>
504
- <form name="leave-organization" action="{% url 'bom:settings' tab_anchor=ORGANIZATION_TAB %}"
505
- method="post" enctype="multipart/form-data">
506
- {% csrf_token %}
507
- <div class="right-align">
508
- <button class="waves-effect waves-light btn red lighten-1" type="submit"
509
- name="submit-leave-organization">
510
- <i class="material-icons left">exit_to_app</i>Leave Organization
511
- </button>
550
+ <div id="integrations" class="settings-section">
551
+ {% if perms.bom.manage_members %}
552
+ <div class="section">
553
+ <h4 class="section-title"><i class="material-icons teal-text text-darken-1">integration_instructions</i>Integrations
554
+ </h4>
555
+ <div class="section">
556
+ <h5 class="section-title"><img style="height: 1em; margin-right: 4px;"
557
+ title="Via Google Drive"
558
+ src="{% static 'bom/img/google_drive_logo.svg' %}">Part File
559
+ Storage with Google Drive</h5>
560
+ {% if not google_authentication %}
561
+ <p>Connect your Google account to access Google Drive features.
562
+ {% if not organization.google_drive_parent %}Organization owners can enable file
563
+ storage
564
+ using Google Drive. {% if organization.owner == user %}Since you are the owner,
565
+ you are
566
+ able to enable file storage!{% else %}Contact your organization owner to enable.
567
+ {% endif %}{% endif %}</p>
568
+ <p>When you connect, we will create a folder called <b>IndaBOM Part Files</b> in your
569
+ root of
570
+ Google Drive (and it can be moved anywhere in your drive). To add files to a part,
571
+ navigate
572
+ to the part in IndaBOM, and on the part's <b>Specifications</b> tab, click the <img
573
+ title="Via Google Drive" style="width: 16px; vertical-align: middle;"
574
+ src="{% static 'bom/img/google_drive_logo.svg' %}"> Google Drive link. This
575
+ will
576
+ create a folder for your part in your root IndaBOM directory, or take you there if
577
+ it
578
+ already exists.</p>
579
+ <p>You'll be able to access the files directly through Google Drive, and through
580
+ IndaBOM.</p>
581
+ {% else %}
582
+ <p>You're connected with Google and can access Google Drive features.</p>
583
+ {% endif %}
584
+ <div>
585
+ {% if google_authentication %}
586
+ <p>Logged in to Google as: {{ google_authentication.uid }}</p>
587
+ <div class="right-align">
588
+ <form action="{% url 'social:disconnect' 'google-oauth2' %}" method="post">
589
+ {% csrf_token %}
590
+ <button class="waves-effect waves-light btn btn-primary" type="submit">
591
+ Disconnect
592
+ </button>
593
+ </form>
594
+ </div>
595
+ {% else %}
596
+ <p>To get started, sign in with Google:</p>
597
+ <div class="right-align">
598
+ <a href="{% url "social:begin" "google-oauth2" %}">
599
+ <img title="Google sign-in."
600
+ src="{% static 'bom/img/google/web/1x/btn_google_signin_dark_normal_web.png' %}">
601
+ </a>
602
+ </div>
603
+ {% endif %}
604
+ </div>
512
605
  </div>
513
- </form>
514
- </div>
515
- {% else %}
516
- <div class="section">
517
- <h4 class="section-title">You're not part of any organization</h4>
518
- <p>To create your organization, start <a href="{% url 'bom:home' %}">here</a>.</p>
519
- </div>
520
- {% endif %}
606
+ <div class="section">
607
+ <h5 class="section-title"><img style="height: 1em; margin-right: 4px;"
608
+ title="Sourcing via Mouser.com"
609
+ src="{% static 'bom/img/mouser.png' %}">Automagic Sourcing
610
+ via Mouser</h5>
611
+ <p>Currently under construction.</p>
612
+ </div>
613
+ </div>
614
+ {% else %}
615
+ {% include 'bom/nothing-to-see.html' with required_privilege='Admin' %}
616
+ {% endif %}
617
+ </div>
521
618
  </div>
522
619
  </div>
523
-
524
620
  {% endblock %}
525
621
 
526
622
  {% block bom-script %}
623
+ <style>
624
+ .settings-section {
625
+ display: none;
626
+ }
627
+
628
+ .settings-section.active {
629
+ display: block;
630
+ }
631
+ </style>
527
632
 
528
- <!-- Handle if there's an anchor, select tab -->
633
+ <!-- Handle navigation -->
529
634
  <script type='text/javascript'>
530
- var tabsElem = document.querySelector('.tabs');
635
+ $(document).ready(function () {
636
+ function showSection(sectionId) {
637
+ if (!sectionId) sectionId = '#user';
638
+ if (!sectionId.startsWith('#')) sectionId = '#' + sectionId;
639
+
640
+ $('.settings-section').removeClass('active');
641
+ $(sectionId).addClass('active');
531
642
 
532
- {% if tab_anchor %}
533
- $('#{{ tab_anchor }}-tab').addClass('active');
534
- {% endif %}
643
+ $('.settings-nav .collection-item').removeClass('active');
644
+ $('.settings-nav .collection-item[href="' + sectionId + '"]').addClass('active');
645
+
646
+ // Update URL without jumping
647
+ if (window.location.hash !== sectionId) {
648
+ history.pushState(null, null, sectionId);
649
+ }
650
+ }
535
651
 
536
- var tabs = M.Tabs.init(tabsElem);
652
+ $('.settings-nav .collection-item').on('click', function (e) {
653
+ e.preventDefault();
654
+ var sectionId = $(this).attr('href');
655
+ showSection(sectionId);
656
+ });
657
+
658
+ // Initial section based on hash or tab_anchor
659
+ var initialSection = window.location.hash;
660
+ {% if tab_anchor %}
661
+ if (!initialSection) {
662
+ {% if tab_anchor == 'indabom' %}
663
+ initialSection = '#part-classes';
664
+ {% elif tab_anchor == 'organization' %}
665
+ initialSection = '#organization';
666
+ {% elif tab_anchor == 'user' %}
667
+ initialSection = '#user';
668
+ {% else %}
669
+ initialSection = '#{{ tab_anchor }}';
670
+ {% endif %}
671
+ }
672
+ {% endif %}
673
+
674
+ showSection(initialSection);
675
+
676
+ // Handle back/forward buttons
677
+ window.onpopstate = function () {
678
+ showSection(window.location.hash);
679
+ };
680
+ });
537
681
  </script>
538
682
 
539
683
  <script type='text/javascript'>