Multi level depending tags?

Hell TW Community,

I am looking for a solution to the following problem.
The challenge is as follows:

I want to manage assets in wiki due to the fact that I am using the same TW also for other topics and it is accepted. But I fail to realize the different responsibilities.

There are unique named assets I want to combine with location and departments

  • asset_1 = USB sticks
  • asset_2 = cloud storage from ABC
  • asset_3 = Photos
  • location_1 = Frankfurt
  • location_2 = New York
  • location_3 = Old Hamburg Village
  • department_1 = Human resource
  • department_2 = Research and development
  • department_3 = Sales
  • department_4 = Purchasing
  • asset_encryption = yes / no

An example:

  1. The asset_1 is a USB stick.
  2. USB Sticks (asset_1) will be available in location_1 and location_2 but not in location_3
  3. USB Sticks (asset_1) are stored in location_1 at department_1 and deparment_2, in location_2 in department_2 and department_3
  4. USB Sticks (asset_1) in location1 department 1 are encrypted, also in location 2 department_3
  5. The asset_2 is a cloud storage provided by ABC
  6. asset_2 is available in location_2 departement_1 and department_3, also in location_3 department_1
  7. The asset_2 in location_3 department_1 is encrypted

First, I tried to use tags but this is only working for locations, because not all locations have all départements.
Second the combination of tags and fields is also failing.

And at the end I have to keep in mind that I want to generate overviews about all assets used in department_1 or location_2 or a combination of that or other combinations.

Any idea is welcome especially with a solution how to implement it.

Thank you in advance
Stefan

If I were you, I would show your requirements to a database guy. By no means am I implying that TiddlyWiki might be the wrong tool for the job, but your requirements look very much like a database specification of tables and views. Maybe it’s just my instinctive fear of long and complex wikitext filters.

I second @vuk’s point that TW might not be the best tool for the task, if this database is supposed to be very complex.

Anyway, if you stay in TW,

This issue could be solved by having specific tags for a departament at a location, each tagged with the general location and general departament type, e.g.

                  Department
				    /
Location ----------------
    |             /       \
Frankfurt        HR      New York
     \          /  \    /
	 Frankfurt HR   NY HR
	     /|\         /|\
   assets in FrHR   assets in NY HR

This way you can have any number of interleaved trees and precisely categorize many things using just tags.
Retrieving the “endpoints” might be one problem if this structure is too deep – the kin plugin/filter could be of help in such case.

1 Like

I’d argue that one of the things TW does best is to serve as a custom database for small- to medium-sized datasets. I’ll see if I can create a demo of how I’d do this. But my first thought would be to create tiddlers for Assets, Locations, and Departments, then have data tiddlers which have asset, department, location and encrypted fields, and add view templates for each of these types of tiddlers.

1 Like

I think there is not enough information in your examples. Eg: You mention, that assets are encrypted or plain text at different departments.

The question is:

  • Is “encrypted” a property of asset or a property of location_1 department_1 ?

Eg: If an asset is at location 1 department 1

  • Does it have to be encrypted, because it is stored there?
  • What about cloud assets. Do they need to be encrypted if they are used at location_1 dep_1?
  • If an “unencrypted” asset (USB stick) moves to location_1 dep_1 – Does it’s state need to be changed to encrypted?

I did write a concept, how I would structure it. But without knowing the answers for the questions above it does not make sense to post the concept, because it will be inconsistent.

1 Like

Ok, basic demo created: http://scott.sauyet.com/Tiddlywiki/Demo/AssetPlacementDemo/v1/.

I have created Assets, Locations, and Departments to match your data, each with a tag of “Asset”, “Location”, or “Department”. I also created the tag “AssetPlacement”, which isn’t a great name. I assume you can find something better.

The Asset Placement tiddlers look like this:

title: Asset Placement 3
tags: AssetPlacement
asset: Asset/1
department: Department/2
encrypted: no
location: Location/2

There is a new button in the toolbar to create an AssetPlacement. It creates a tiddler with the right tag, a sequential title, and fields for asset, location, department, and encryption. These are chosen by dropdowns populated from the appropriately tagged tiddlers:

I have templates for the Asset and the AssetPlacement. We could easily add more for Locations and Departments.

I’ll try to get on later to explain more about how it works, if something isn’t clear.

1 Like

I think there’s a structural type-token confusion embedded in your description (or perhaps it’s just a language barrier).

An asset (singular) should have a location, and an encryption status (etc.) as appropriate.

It sounds like USB Sticks is a category of assets. You need unique identifiers, or some kind of virtual identifiers, for particular individual USB-sticks (or sets, if a set in a location never needs further individuation). That way, various properties and attributes can properly attach to the individuals (or subsets), not with the wider category.

Agreed. I glossed this over in my attempt. Especially unclear to me is whether – assuming these actually are meant to be asset categories – we could have multiple categories of an asset in a Location/Department? Could we have encrypted and unencrypted USB Sticks in Frankfurt/Sales?

1 Like

Hello @Scott_Sauyet, @pmario, @Springer,

@Scott_Sauyet I bend my knee in front of you about the idea and the first solution. And I want to understand really how you did that due to the fact that I don’t see code in your example.

To answer hopefully the open question.

  • The the encrytion is a yes/no information related to a asset what is used in a location in a department.
    A USB Stick can be yes(encrypted) at HR in Frankfurt, but of course a USB Stick (not physically the same) can be used unencrypted in HR New York.
    And realistically the HR department in Frankfurt can have USB Sticks encypted and unencrypted.
    I don’t generate a list about all USB Sticks like USB_Stick_1 … USB_Stick_n.
    An asset is a group of something in different locations and departments.

If I look to the demo it is the right way.
Is there a possibility to have a flexible filter gui for a user or how it works?
My idea for this filter is to have Asset, Departement, Location and Encryption as a selection field and dynamically the list will displayed fulfilling the filter condition.

I am curious to know how you realized this because I could also use this kind of implementation for other topics.

Stefan

hmm, IMO that does not make sense to me. If there can be both, encryption does not have any sense, since users will delete the encrypted USB stick and overwrite it with the unencrypted one, because it is more convenient.

If that’s the case. Asset is only meta data for location and department. They are not tracked at all.

How do you intend to “track” USB data updates, if you do not know, which USB stick contains which version of the data?

Hi @pmario,

my perspective is a different point of view.
I have to manage the assets not the content.
Why a department should have 2, or more, USB Sticks with different states?
The situation is that the département has to use encrypted USB Sticks if they need to transport data what is classified (eg private data/GDPR) but they have to use the unencrypted USB stick due to the fact that the terminal to read out the data for coming and leaving an area is not working with encrypted USB Sticks.

Later on I will expand this asset management solution to other assets.
Think about a drawing in an engineering department. There are drawings need to be classified in different levels. There is no need to list the hundreds or thousands of drawings. All drawings can be grouped differently. One group is classification level, another if it is a drawing from the customer or a supplier or owed by us, and much more.

And if I stretch my phantasies than I can think about a requirement management also using the same solution from @Scott_Sauyet.

That what @Scott_Sauyet implemented could be extended to have also a level above to generate the different views. So; the tag information can be handled by a level above like “Asset Management” what is defining that here “Asset”, “Location”, “Department”, “Encryption” is part of that. And another management system like “Requirement Management” could contain “Customer”, “Département”, “Norm to fulfill”.

Stefan

I posted another version, at

http://scott.sauyet.com/Tiddlywiki/Demo/AssetPlacementDemo/v2/

It adds a little dummy content and templates for Location and Department.

I’m sorry if some of the following is review. I’m sure you know parts of it; I just don’t know which parts. I’m also sure there are things missing; feel free to ask for clarification.

I tend to put my internal stuff in system tiddlers. You can see them in the system sub-tab of the More tab of the sidebar. They all have the prefix $:/_/demo. You can also see them by filtering on [prefix[$:/_/demo]].

There are a few groups of tiddlers in there:

View Templates

To add common content to one of our main items (Locations, Departments, Assets, AssetPlacement), we use a View Template. A View Template adds content to the rendering of a tiddler. It could be a new toolbar, title/subtitle field, or in our case, a section to follow the body. Here we discuss the one for Location, but Location and Asset are very similar, and AssetPlacement is quite simple.

The code is at $:/_/demo/templates/location

title: $:/_/demo/templates/location
tags: $:/tags/ViewTemplate

<% if [<currentTiddler>tag[Location]] %>

<$let location=<<currentTiddler>> >

<$list filter="[tag[AssetPlacement]location<location>get[department]unique[]sort[caption]]" variable="department">
<h3><$link to=<<department>> ><$text text={{{ [<department>get[caption]] }}}/></$link></h3>
<ul>
<$list filter="[tag[AssetPlacement]location<location>department<department>get[asset]unique[]sort[caption]]" variable="asset">
<li><$link to=<<asset>> ><$text text={{{ [<asset>get[caption]] }}}/></$link></li>
<ul>
<$list filter="[tag[AssetPlacement]asset<asset>location<location>department<department>]" variable="placement" counter="cnt">
<li><$link to=<<placement>> ># <$text text= {{{ [<placement>removeprefix[Asset Placement ]] }}} />. (<$text text={{{ [<placement>get[encrypted]match[yes]then[encrypted]else[unencrypted]] }}} />)</$link></li>
</$list>
</ul>
</$list>
</ul>

</$list>
</$let>

<% endif %>

First, we see that this tiddler has the tag $:/tags/ViewTemplate. This is what tells TW to use this as a partial template for every tiddler. There are ways to order these, using list-before and list-after fields on this tiddler, or using the list field of the $:/tags/ViewTemplate tiddler. But we accept the default behavior, which puts this template after the body (the wikified text field.)

Note that the rest of the code is surrounded by

<% if [<currentTiddler>tag[Location]] %>

<!-- code here -->

<% endif %>

This means that the main part of the code will only apply if our tiddler has the tag Location.

We won’t go through all the details, but briefly, we use nested <$list> widgets to show the Departments within this location, the Assets within those Departments, and the instances (what I’m calling AssetPlacements) of those assets available.

To find the filtered lists of these, we use filters like this:

[tag[AssetPlacement]location<location>department<department>get[asset]unique[]sort[caption]]

In this case we’re looking for the Assets for a given Location and Department by first finding all the AssetPlacements with proper location and department fields, extracting the asset field, finding the unique set of those Assets, and sorting on the caption.

Note: (Across this wiki, I use titles such as Asset/1, Asset/2, Location/42, etc, and use the caption in to hold the useful description. This isn’t critical for small sets of data, but it gets useful as the data grows. It also means that I can use the tiddler title “New York” or “Sales” for other purposes than this data. Below I describe how this ends up showing as the title.)

That will give us a list of Assets. For instance, for New York/Sales, it gives us a list like

  • Asset/2
  • Asset/1

which have captions:

  • Cloud storage from ABC
  • USB stick

The markup shows how these are used to display the Asset categories.

The Department and Asset templates are very similar, and $:/_/demo/templates/placement is just a simple table showing the field values as links.

Asset Placement Creation Button

To create a new Asset Placement, we hit a button. The tiddler for that looks like:

title: $:/_/demo/core/ui/Buttons/new-asset-position
tags: $:/tags/PageControls
caption: New Asset Placement
description: Create a new asset placement

\define new-position-action()
<$action-createtiddler
  $basetitle="Asset Placement"
  tags="AssetPlacement"
  asset=""
  location=""
  department=""
  encrypted="">
  <$action-navigate $to=<<createTiddler-title>>/>
  <$action-sendmessage $message="tm-edit-tiddler" $param=<<createTiddler-title>>/>
</$action-createtiddler>
\end

<$button actions=<<new-position-action>> tooltip={{$:/_/demo/buttons/new-asset-position!!description}} aria-label={{$:/_/demo/buttons/new-asset-position!!caption}} class=`$(tv-config-toolbar-class)$ new-asset-position`>
{{$:/core/images/plus-button}}
<span class="tc-btn-text">
{{!!caption}}
</span>
</$button>

This has tag $:/tags/PageControls, which puts it on the right-hand toolbar.

This involves an ActionCreateTiddlerWidget and a ButtonWidget that calls it. The action widget creates a new tiddler, using the appropriate tag, placeholders for the four custom fields (asset, location, department, and encrypted) and a title generated from the base title Asset Placement. This generates titles like Asset Placement 1 or Asset Placement 42 depending upon what’s already in the wiki. I would prefer to match my convention and make it AssetPlacement/1 and AssetPlacement/42, but I don’t know how to autogenerate that.

Inside that action widget are two more widgets, one to navigate to the new tiddler, and a second to change it to edit mode. There is a simpler alternative to this shuffle, tm-new-tiddler, but I don’t know how to combine that with title generation.

The button is simple enough, pointing to this action, including tooltips and such. The content is an image icon (I just chose one from TW’s internal set, but you can include whatever you like), and some text.

When you click the button, a new Asset Placement tiddler is created, and opened in edit mode. You may note that the empty custom fields have dropdowns. We create those in the next section.

Field Editor Filters

Customizing EditTemplate field rendering describes how you can customize the editing for a field. In our case, we want to use dropdowns choosing from appropriate assets, locations, and departments, and deciding whether the asset is encrypted. Here we focus on the department.

There are two tiddlers used for this, and they’re both fairly simple:

$:/_/demo/config/FieldEditorFilters/department

looks like this:

title: $:/_/demo/config/FieldEditorFilters/department
tags: $:/tags/FieldEditorFilter
list-before: $:/config/FieldEditorFilters/default

[match[department]then[$:/_/demo/config/EditTemplateFields/Templates/department]]

The tag $:/tags/FieldEditorFilter marks this as part of the Field Editor Cascade. The list-before field means this will run before the default field editor.

The single filter in the body is used by this cascade to check if the field name is “department”, and if so, chooses the following tiddler for the editor:

$:/_/demo/config/EditTemplateFields/Templates/department

title: $:/_/demo/config/EditTemplateFields/Templates/department

<$select tiddler=<<currentTiddler>> field=<<currentField>> class="tc-edit-texteditor tc-edit-fieldeditor" tabindex={{$:/config/EditTabIndex}} cancelPopups="yes">
    <$list filter='[tag[Department]sort[caption]]'>
        <option value=<<currentTiddler>>><$view field='caption'/></option>
    </$list>
</$select>

This simply finds all tiddler with the tag Department, sorts them by caption and creates a <$select> widget with those values.

There are similar pairs for location and asset fields. For encrypted, we have something very similar, but the editor is not as specific. It points to a generic yes-no choice rather than a dropdown. (I would probably eventually refactor this to use a checkbox or radio buttons instead.)

Miscellaneous

Using caption instead of title

Also included is the code for another cascade used to set the display title, using the caption field instead of the title. It uses these two tiddlers:

$:/_/demo/config/ViewTemplateTitleFilters/caption

title: $:/_/demo/config/ViewTemplateTitleFilters/caption
list-before: $:/config/ViewTemplateTitleFilters/default
tags: $:/tags/ViewTemplateTitleFilter

[<currentTiddler>has[caption]then[$:/_/demo/core/ui/ViewTemplate/title/caption]]

and

$:/_/demo/core/ui/ViewTemplate/title/caption

title: $:/_/demo/core/ui/ViewTemplate/title/caption

\whitespace trim
<h2 class="tc-title">
<$view field="caption"/>
</h2>

Styles

There is also a small custom stylesheet, used here only to format the table in the Asset Placement template:

$:/_/demo/styles/css

title: $:/_/demo/styles/css
tags: $:/tags/Stylesheet
type: text/css

table.asset-placement {
  th, td {padding: .25em .5em;}
  th {text-align: right;}
}

The tag $:/tags/Stylesheet means that this will be used as a CSS stylesheet. The type text/css will help the content display better in the view.


There’s a lot here. Please tell me what does not make sense.

Certainly, but I won’t have time to attempt one before the weekend. There might be some suggestions in certain threads here.

3 Likes

Hi @Scott_Sauyet,

thank you so much for your explanation here. I am proud of myself to understand more and more how you implement it.
So far as I was able to understand I adapted it also to my requirements and it is working well.

Could you please help me to create another overview?

I started to have 3 selection fields and to build a table but I fail to fill the table with the right content because it should only contain these assets selected by the user. And also I fail in the case of an empty entry in one of the selection fields.

<$select tiddler='Filter' field='Asset' default='Asset'>
<$list filter='[tag[Asset]sort[title]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>

<$select tiddler='Filter' field='Department' default='Department'>
<$list filter='[tag[Department]sort[title]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>

<$select tiddler='Filter' field='Location' default='Location'>
<$list filter='[tag[Location]sort[title]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>

<$tiddler tiddler={{Filter!!Department}}>
<$transclude mode='block'/>
</$tiddler>

<table class="asset-placement">
<td>
<th>Asset</th>
<th>Location</th>
<th>Department</th>
<th>Encrypted</th>
</td>
</table>

Thank you in advance
Stefan

1 Like

I created a third version: http://scott.sauyet.com/Tiddlywiki/Demo/AssetPlacementDemo/v3/ that adds what I think you’re looking for. This adds the single tiddler, Filter, which both holds the data as your code suggested and creates the UI. But you could move the code anywhere else, and it would still use Filter for the data fields. (If you have to change the name Filter, it’s a bunch of changes in the code, though; replace all uses of "Filter" [with the capital F] with your new title.)

The important parts here are:

Formatting a filter string

We’re going to want a filter like this:

[tag[AssetPlacement]!has[draft.of]]

if none of our dropdowns are selected, but like

[tag[AssetPlacement]!has[draft.of]] :filter[[Location/2]match{!!location}]

if we’ve chosen Location/2 (New York),

or like

[tag[AssetPlacement]!has[draft.of]] :filter[[Asset/1]match{!!asset}] :filter[[Department/3]match{!!department}]

if we’ve chosen Asset/1 (USB sticks) and Deparment/3 (Sales), and so on.

We do this by creating filter runs for Assets, Locations, and Departments, and then choosing whether to use them or just a blank expression, based on whether the corresponding select box has a value. To do this we use this code:

<$let
  amatch= `:filter[[${ [{Filter!!Asset}] }$]match{!!asset}]` 
  afilter= {{{ [{Filter!!Asset}match[]then[]else<amatch>] }}}

  lmatch= `:filter[[${ [{Filter!!Location}] }$]match{!!location}]` 
  lfilter= {{{ [{Filter!!Location}match[]then[]else<lmatch>] }}}

  dmatch= `:filter[[${ [{Filter!!Department}] }$]match{!!department}]` 
  dfilter= {{{ [{Filter!!Department}match[]then[]else<dmatch>] }}}

  query = `[tag[AssetPlacement]!has[draft.of]] $(afilter)$ $(lfilter)$ $(dfilter)$`
>

We look at the first pair, for Assets. The ones for Location and Department are quite similar.

 amatch= `:filter[[${ [{Filter!!Asset}] }$]match{!!asset}]` 

creates the filter run string for selecting tiddlers that match the selected Asset. If you haven’t seen Substituted Attribute Values before, then inside backtick-delimited strings (`), we can use substitute value for filter expressions by wrapping them in this syntax:

${ [{Filter!!Asset}] }$

the ${ - }$ pair wrap a filter expression whose value will be used instead. There is a similar syntax for including variables, using a $( - )$ pair, which we use below in defining the query.

Now this

  afilter= {{{ [{Filter!!Asset}match[]then[]else<amatch>] }}}

selects either that filter or the empty string, based on whether there is a value in the field, which is controlled by one of the dropdowns.

After we create these for Asset, Location, and Department, we combine them with this line:

  query = `[tag[AssetPlacement]!has[draft.of]] $(afilter)$ $(lfilter)$ $(dfilter)$`

Again this uses substituted attribute values.

Filter Usage

The important thing to realize is that what we have now is a String representation of a filter expression. We can use it directly, like this:

<$list filter=<<query>> >

or we can extend it to include a message to indicate that there are no records found:

<$list filter=`$(query)$ +[count[]match[0]]`>
  <tr><td colspan="5" style="text-align: center; color: red;">No matching records</td></tr>
</$list>

The rest of that tiddler is the markup for the select boxes and for the display table.


I’m guessing the smart folks here may have improvements to suggest. But this seems to work reasonably well.

@Scott_Sauyet

THIS IS AWESOME !!!

I was not aware of this possibilities to substitute values for filter expressions like this. It will take me days or weeks to understand how it works ( :wink: please remember that my time of developing software endet with assembler and native C ).

I will try to convert your code for my usage. I think I can replace step by step the Filterby <<currentTiddler>> to make it a little bit more universal.

As you promised I hope that someone else here like the idea like me and sees the possibilities that arise with the functions you have developed. I could imagine that this could be turned into a framework or plugin that makes it possible to use several of these quasi-databases in one TW.

I am very happy with this solution. I can make the necessary adjustments for my application (there are even more fields to be linked) myself with your explanations.

Thank you very much
Stefan

:blush: Glad you like it.

You definitely can. From the code snippet you supplied above for the <select> options, I thought there was a good chance that you were storing the field data in a different location from the UI. If you’re not doing so, then <currentTiddler> (or a shorter alias) would be clearer. There is a good reason to do what I did in many circumstances, though: basically whenever the effects of changing that field value are felt in multiple places in the wiki. If you don’t need that, currentTiddler is clearly better.

I would argue the “quasi” in there! :slight_smile:

I don’t think of this as something that could become a plugin or even an edition. It’s a style of working. I suppose I can see the possibility of a wiki generator built on these ideas, but I don’t have any inclination to build such a thing.

I did start a wiki to explain some of these ideas. (In fact, you were in on some of the discussion about it.) I’ve set it aside until I gain more TW experience needed to proceed. But I would like to sometime soon get back to https://crosseye.github.io/TW5-SQL_Playground/.

Hi @Scott_Sauyet,

I don’t think of this as something that could become a plugin or even an edition. It’s a style of working. I suppose I can see the possibility of a wiki generator built on these ideas, but I don’t have any inclination to build such a thing.

Me too :wink: But, together with the SQL Playground, maybe someone else will to it.

First of all, I must emphasize that I was only able to make the changes listed here because you explained them in such detail.

I made some changes to your code and want to share them here for other users.
Changing the Name Filter in the Tiddler with <<currentTiddler>> was not successful within the $let section.
The line

  amatch= `:filter[[${ [{<<currentTiddler>>!!Asset}] }$]match{!!asset}]` 

is not working like expected the other changes are working well.

But I was able to change the UI a litte bit more end user friendly.

<$let
  amatch= `:filter[[${ [{Filter!!Asset}] }$]match{!!asset}]` 
  afilter= {{{ [{Filter!!Asset}match[]then[]else<amatch>] }}}
  lmatch= `:filter[[${ [{Filter!!Location}] }$]match{!!location}]` 
  lfilter= {{{ [{Filter!!Location}match[]then[]else<lmatch>] }}}
  dmatch= `:filter[[${ [{Filter!!Department}] }$]match{!!department}]` 
  dfilter= {{{ [{Filter!!Department}match[]then[]else<dmatch>] }}}
  query = `[tag[AssetPlacement]!has[draft.of]] $(afilter)$ $(lfilter)$ $(dfilter)$`
>
<table class="asset-placement">
  <tr>
    <th></th>
    <th>Asset</th>
    <th>Location</th>
    <th>Department</th>
    <th>Encrypted</th>
  </tr>
  <tr>
    <th></th>
    <th>
<$select tiddler=<<currentTiddler>> field='Asset' default='Asset'>
<option value="">(any)</option>
<$list filter='[tag[Asset]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
    </th>
    <th>
<$select tiddler=<<currentTiddler>> field='Location' default='Location'>
<option value="">(any)</option>
<$list filter='[tag[Location]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
    </th>
    <th>
<$select tiddler=<<currentTiddler>> field='Department' default='Department'>
<option value="">(any)</option>
<$list filter='[tag[Department]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
    </th>
    <th></th>
  </tr>
<$list filter=<<query>> >
  <tr>
    <td><$link><$text text={{{ [{!!title}removeprefix[Asset Placement ]] }}}/></$link></td>
    <td><$link to={{{ [{!!asset}] }}}><$text text={{{ [{!!asset}get[caption]] }}}/></$link></td>
    <td><$link to={{{ [{!!location}] }}}><$text text={{{ [{!!location}get[caption]] }}}/></$link></td>
    <td><$link to={{{ [{!!department}] }}}><$text text={{{ [{!!department}get[caption]] }}}/></$link></td>
    <td>{{!!encrypted}}</td>
  </tr>
</$list>
<$list filter=`$(query)$ +[count[]match[0]]`>
  <tr><td colspan="5" style="text-align: center; color: red;">No matching records</td></tr>
</$list>
</table>
</$let>

Also I made changes in the $:/_/demo/templates/placement Tiddler to give the user the possibility to change the data without joining the edit mode.

<% if [<currentTiddler>tag[AssetPlacement]] %>

<table class="asset-placement">
<tr>
<th>Asset</th>
<td><$link to={{{ [{!!asset}] }}} ><$text text={{{ [{!!asset}get[caption]] }}}/></$link></td>

<td><$select tiddler=<<currentTiddler>> field='asset' default='asset'>
<$list filter='[tag[Asset]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
</td>
</tr>

<tr>
<th>Location</th>
<td><$link to={{{ [{!!location}] }}} ><$text text={{{ [{!!location}get[caption]] }}}/></$link></td>

<td><$select tiddler=<<currentTiddler>> field='location' default='location'>
<$list filter='[tag[Location]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
</td>
</tr>


<tr>
<th>Department</th>
<td><$link to={{{ [{!!department}] }}} ><$text text={{{ [{!!department}get[caption]] }}}/></$link></td>

<td><$select tiddler=<<currentTiddler>> field='department' default='department'>
<$list filter='[tag[Department]sort[caption]]'>
<option value=<<currentTiddler>>><$view field='caption'/></option>
</$list>
</$select>
</td>
</tr>

<tr>
<th>Encrypted</th>
<td>{{!!encrypted}}</td>

<td><$select tiddler=<<currentTiddler>> field='encrypted' default='encrypted'>
<option value="yes">Yes</option>
<option value="no">No</option>
<option value=<<currentTiddler>>></option>
</$select>
</td>
</tr>

</table>

<% endif %>

And to have a unique UI I changed also the mode of creation a AssetPlacement with your button $:/_/demo/core/ui/Buttons/new-asset-position . Now the tiddler will be created and the same UI will appear.

\define new-position-action()
<$action-createtiddler
  $basetitle="Asset Placement"
  tags="AssetPlacement"
  asset=""
  location=""
  department=""
  encrypted="">
  <$action-navigate $to=<<createTiddler-title>>/>
</$action-createtiddler>
\end

<$button actions=<<new-position-action>> tooltip={{$:/_/demo/buttons/new-asset-position!!description}} aria-label={{$:/_/demo/buttons/new-asset-position!!caption}} class=`$(tv-config-toolbar-class)$ new-asset-position`>
{{$:/core/images/plus-button}}
<span class="tc-btn-text">
{{!!caption}}
</span>
</$button>

I will share further improvements here also.

Thank you
Stefan

Glad to help. This has been fun.

There’s a syntax error there. Inside a filter, we do not double the braces, either angle- or curly-braces.

So instead of this:

amatch= `:filter[[${ [{<<currentTiddler>>!!Asset}] }$]match{!!asset}]` 

We need this:

amatch= `:filter[[${ [{<currentTiddler>!!Asset}] }$]match{!!asset}]` 
<!--                  ^---------------^-------- only one brace   -->

My latest version incorporates this, with a slight twist, defining a config variable at the beginning of the let statement that is set to <<currentTiddler>>. However, it’s not working thoroughly, and at some time I’ll try to figure out why.

After moving the <$let> statement to the very top, I start it with this variable

<$let
  config=<<currentTiddler>>

That works when I replace

<$select tiddler='Filter' field='Asset'...

with

<$select tiddler=<<config>> field='Asset'...

and when I replace

  amatch= `:filter[[${ [{Filter!!Asset}] }$]match{!!asset}]` 

with

  amatch= `:filter[[${ [<config>get[Asset]] }$]match{!!asset}]`

but for some reason things fail when I replace this:

  afilter= {{{ [{Filter!!Asset}match[]then[]else<amatch>] }}}

with

  afilter= {{{ [<config>get[Asset]match[]then[]else<amatch>] }}}

I really can’t see why, though. I’ll try to come back to it after some time away. One big advantage of this approach—once it’s working—is that we could switch from a standard tiddler to a temporary tiddler, so that when the wiki is reloaded, these are reset to the default any. It may not be an issue for a single-user wiki, but for a shared one, it’s probably a good idea.

That’s a definite improvement.

I have a new version, http://scott.sauyet.com//Tiddlywiki/Demo/AssetPlacementDemo/v4/. This implements your UI changes. I also added a selector for encryption status, which you may or may not want.

The other change you added is the template for the Asset Placement items, so that changing the fields can be done from the View screen, without a need to enter the Edit screen.

I have mixed feelings about this. On the plus side, this could allow you to remove a bunch of single-purpose tiddlers, those tiddlers in the namespace $:/_/demo/config/EditTemplateFields or $:/_/demo/config/FieldEditorFilters, eight in total. And it simplifies the button. On the minus side, I feel it might make your data too casually editable. Someone clicking on an Asset Placement, who’s already used to clicking such dropdowns in the Filter screen, could easily make changes, without realizing it at all. Suddenly a USB stick should have magically moved from Frankfurt to New York and been decrypted in the process!

1 Like
afilter={{{ [<config>get[Asset]match[]then[]else<amatch>] }}}

This fails because the get[] filter operator only returns a result if the indicated field contains a non-blank value.
Thus, when the Asset field is blank, the match[]then[] clause is skipped and the else<amatch> clause is applied instead.

I suggest using:

afilter={{{ [<config>has[Asset]then<amatch>] }}}

which tests to see if the Asset field is non-blank and, if it is, it sets afilter to the amatch value; otherwise, it sets afilter to a blank value.

-e

3 Likes

Hi @Scott_Sauyet,

We need this:

amatch= `:filter[[${ [{<currentTiddler>!!Asset}] }$]match{!!asset}]` 
<!--                  ^---------------^-------- only one brace   -->

Oh, sometimes it is too easy to see the solution.

I think I will use both UIs for the placement. One “read only” and the other for editing, what is much more user friendly than the edit mode :slight_smile:

I observed a strange behaviour if there are more than 10 placements defined the Filter is displaying 1, 10, 2, 3 … . I see only a sort in the filter of assets, department and location but not for placements. Or is it build in and I have to take care of the number format (the old problem of sorting an ascii text with numbers in it)?

We need this:

image

Further tests and improvements will be done next week if I present it to my users :smiley:

Nice weekend
Stefan