field customization
introduction
Each section of a topic-card can be populated by links. These links are constructed from declarative field definitions. When a user clicks on such a link, it can trigger some kind of action.
There are several types of actions a field can trigger:
- Open a link in the content area. This can be an self-hosted app URL, or a remote website which allows being embedded (without CORS issues).
- Open a link in a new browser tab. This is sometimes required when the website does not allow being embedded in a 3rd-party iframe or user-authentication is required.
- Show an inline view in the sidebar. There are some variations of this:
- Show a list of items from the Wikidata entity. (The field needs to have the multi-value key set to “true” in Conzept and also contain multiple values in Wikidata. If there is only one item in Wikidata, the field will be rendered as a single link to the Wikipedia/Wikidata page.)
- Show a list of items fetched from an API. These type of actions also require some code support to fetch the API data.
- Show an inline iframe from an URL
- Trigger some code to run when the link is clicked. Examples: create a new bookmark or start/stop playing an audio file.
You can see all the fields used for the Conzept website in the “src/data/field.js” file. Once you have added one or more new field definitions to this file:
- Update the version setting in “/etc/conzept/settings.conf”
- Run “npm run build” in the “app/explore2/” directory.
field processing
The field list is processed in two phases. Normally, you wont need to understand the details of these stages, but sometimes understanding them can help how to create more complicated field definitions.
The first phase is the input phase, where all the field data is collected from external sources such as Wikidata and other API's. This phase has three stages: pre-create, create and post-create. See: setWikidata.js and the API fetch functions.
The second phase is the render phase where fields are processed for display to the user (since all the data is now available), and has two stages: pre-render and render. See: createItemHtml.js.
For each topic listed in the search results, Conzept will check all the defined fields, to find the usable ones. When a field is used, it will set a value (on an internal Conzept data-structure), which will eventually be used to render a link in the user interface.
When a field has a non-false / not-empty value (meaning: “item.<name>” is set to some non-false value), the field is active and will be used for further processing. In all other cases, the field will not be processed further.
The fields are read in order, without any dependency resolving. This also implies, that if you want to use an existing field-value in another field, you need to place that field after it.
field schema
Fields are defined as a list of JavaScript objects with a certain structure.
Each field-object must have a unique name (the object key) and a set of properties (shown in the table below).
All properties are optional, but some types of fields will require certain properties.
Here is a list of the properties that can be used to define fields:
name | data type | description | used in stage |
---|---|---|---|
default_value | <string> | if set: set the “item.<name>” field to this value | pre-create |
value_condition | <eval-string-to-boolean> | if set: and evaluates to “true” ⇒ set “item.<name>” to “true” | create |
value | <eval-string> | ⇒ evaluate this string | create |
create_condition | <eval-string-to-boolean> | if set: and evaluates to “true” ⇒ set “item.<name>” to “true” note: only needed to activate derived-item-fields (as these item-fields don't exist yet) note: a missing or empty “create_condition” defaults to relying on the items current-value | pre-create |
create_trigger | <eval-string> | if the “create_condition” is set to “true” ⇒ evaluate this code-string to achieve extra side-effects during the input-stage | post-create |
render_condition | <eval-string-to-boolean> | if set: and evaluates to “true” ⇒ render this field | pre-render |
render_trigger | <eval-string> | if set AND the “render_condition” is “true” ⇒ evaluate this code-string to achieve extra side-effects during the render-stage | render |
string_format | <eval-string> | string-format used to transform the Wikidata property string or number into custom HTML | create and pre-render |
url_format | <eval-string-to-url> | URL-address-format from Wikidata (or another source), to use when a link is clicked | create and pre-render |
url | <eval-string-to-url> | URL-address to use when a link is clicked | create and pre-render |
title | <eval-string> | link hover-title | pre-render |
prop | <integer> | Wikidata-property number | create |
type | <link | link-split | url | wikipedia-qid | symbol-number | symbol-string> | indicate the type of field | create and pre-render |
mv | <true | false> | indicate if multiple values are allowed | create and pre-render |
icon | <css-class-string> | icon class from FontAwesome or OpenMoji | pre-render |
text | <plain-string> | text under the icon (note: don't use long words here) | pre-render |
section | <plain-string | array-of-strings> | section(s) in which to place the link | render |
rank | <number | array-of-numbers> | position of the link (set for each section) | render |
headline_create | <eval-string> | condition to check whether to display the headline-field | render |
headline_type | <link | link-split | url | wikipedia-qid | symbol-number | symbol-string> | render | |
headline_url | <eval-string-to-url> | (when omitted, defaults to “url”) | render |
headline_icon | <css-class-string> | icon class from FontAwesome or OpenMoji (when omitted, defaults to “icon”) | render |
headline_rank | <number> | position of the field in the topic-headline-row | render |
field types
These types are currently available in field-definitions:
type | required field | description |
---|---|---|
no type | If the field-type is left empty, the data is treated as (one or more) strings by default (but not treated as an “info”-section field, as is done for “symbol-string” and “symbol-number” fields.). | |
wikipedia-qid | prop | Fetch the Wikidata for this property. This will return one or more Wikidata Q-IDs coming from a Wikidata item statement (eg. “Q42”). Note: the “wikipedia-qid” name is used to automatically render either a Wikipedia page or a Wikidata page. Showing the Wikipedia article takes precedence, if it is available in the users' language. |
symbol-number | prop | Number coming from a Wikidata item statement (eg. “3051”). |
symbol-string | prop | String coming from a Wikidata item statement (eg. “+45-111-222-333”). |
symbol-html | prop | This type should only be used when you want create custom HTML-string output, based on some Wikidata item statement string. For example when creating an audio-element HTML string from the audio-file data. |
link | url | Open the URL in a single content-pane |
url | url | Open the URL in a new browser-tab |
link-split | url | Open the URL in two content panes. Load the supplied URL into the first content pane, in the second-content pane we try to load the Wikipedia / Wikidata page for this search-string / qid |
rest-json | “prop: 0”, and “value: '${api-function-name}:${argument-string}':true” | Fetch API data from the supplied API-function and the argument-string (eg. a title-string or qid). The third boolean-argument can enable/disable the API data fetching. The results are rendered in the topic-card. Note: The required field structure is likely to change in the future. Likely becoming a JS-object instead of a colon-delimited string. |
special values
Conzept has various title-forms which can be used anywhere in the field definition values:
name | description |
---|---|
title_no_braces | title without braces |
title_no_braces_lowercase | title without braces in lowercase |
title_ | title without any Wikipedia namespace-prefix and braces (note: also the basis for all the titles below) |
title_enc | title URL-encoded |
title_quoted | title “in quotes” (note: this is the most used title-form, for 3rd-party site searches) |
title_plus | title with a plus for spaces |
title_dashed | title with dash for spaces |
title_lowercase | title in lowercase |
title_no_spaces | title without spaces |
There is currently one 'magic'-variable usable in field-definition values:
name | description |
---|---|
Xvalue | Used to automatically iterate over a list of values (or just one value) coming from Wikidata. This makes it easy to use multi-values to create multiple new strings. See examples of its use here. |
utility functions
Here is a list of often used utility functions, to make the field definitions easier to write and maintain.
name | arguments | output | description | examples |
---|---|---|---|---|
checkLC() | language (string or array-of-strings of language-iso2-codes), country (string or list-of-strings of country-iso-codes) | boolean | Language and/or country check. This function is used for matching against a websites supported languages and/or countries. The country-argument can be omitted. | checkLC( [“fr”,“es”,“zh”,“hi”] ) → true, if any one of these languages is the active user language checkLC(“”,“US”) → true, if the user-country is “US” |
checkTag() | item-object (required), [tag-field-index] (required), tag string or list-of-strings | boolean | Check if a topic has either a certain main-tag (0) or a certain sub-tag (1) tag. | checkTag(item, 0, “person”) → true, if the topic's main-tag is “person” checkTag( item, 1, [“writer”, “written-work” ] ) → true, if topic's sub-class is either “writer” or “work” |
setTags() | item, [ main-tag-string, sub-tag-string ] | (none) | Set main and/or sub-tag of a topic. If either of the tags is left as an empty string, this part will be skipped. | setTags( item, [ “work”, “painting” ] ) → set the main-tag (“work”) and the sub-tag “painting “ |
listed() | list-of-reference-qids, list-of-provided-qids | boolean | check if the provided Qid of the topic | listed( item.instances, [ 3305213 ] ) → check if the topic instance-Qids contains a Qid for painting |
types of fields
There are two main classes of fields: Wikibased-fields and derived fields.
Wikidata-based fields
These fields have a Wikidata property number listed in its “prop:“ value. If a topic has such a Wikidata property value, Conzept will get that data from Wikidata.
examples
An example which renders a link to all the “members of” (Wikidata property) values of a topic:
'member_of' : { // ID of the field (must be unique) title: 'member of', // title of the field (shown when a user hovers over the link) prop: '463', // Wikidata property type: 'wikipedia-qid', // expected data type are Wikidata Qid's mv: true, // multiple values are allowed icon: 'far fa-handshake', // icon shown for the link text: 'member of', // text shown for the link section: ['main'], // which section(s) to show the link in rank: [5160], // position of each link within each section },
An example of a field without a type (which means the data will be treated as a plain string):
'atomic_symbol' : { render_condition: false, // this means we wont show this field in the UI, but just store the value. title: 'atomic symbol', prop: '246', type: '', mv: false, icon: '', text: '', section: '', rank: 1, },
An example for the “number of employees” of a topic:
'employees' : { title: 'employees', prop: '1128', type: 'symbol-number', mv: false, icon: 'fas fa-male', text: '', section: ['main'], rank: [3180], },
The “symbol-html”-type can be used to create customized HTML strings. This example presents an audio element (in the topic card):
'audio_widget' : { create_condition: '${ valid( item.audio ) }', title: 'audio play', prop: '', type: 'symbol-html', mv: false, string_format: '<div id="${item.qid}" class="audio-widget" title="audio" aria-label="audio"><audio class="inline-audio" controls> <source src="${item.audio}"> </audio></div>', icon: '', text: '', section: '', rank: 1, },
An example where the magic variable “${Xvalue}” is used to automatically iterate over a list of values (or just one value) coming from Wikidata. This makes it easy to use multi-values to create multiple new strings.
The example below illustrates the rendering of one or more website URLs.
'website' : { title: 'official website', prop: '856', type: 'url', // open links in a new tab url: '${Xvalue}', // each website URL-value will be rendered as a link mv: true, icon: 'fas fa-home', text: 'site', section: 'main', rank: 40, },
Another example using “${Xvalue}” for a part of the URL:
'twitter_topic' : { title: 'Twitter topic', prop: '8672', type: 'url', url: 'https://twitter.com/i/topics/${Xvalue}', mv: true, icon: 'fab fa-twitter', text: 'Twitter topic', section: ['news-social','main'], rank: [34,9070], },
An example of a headline field:
'gbif_id' : { title: 'gbif_id', prop: '846', type: '', mv: false, icon: '', text: '', section: '', rank: 1, headline_create: 'valid( item.gbif_id )', // create the headline if this value exists headline_type: 'link', headline_url: '${explore.base}/app/response/gbif-map?l=${explore.language}&t=${title_enc}&id=${item.gbif_id}', headline_icon: 'fa-solid fa-binoculars', headline_rank: 275, },
When the field values are mostly the same for the headline, you can omit these:
'chemical_formula' : { title: 'chemical formula', prop: '274', type: 'symbol-html', mv: false, string_format: '<span title="chemical formula">${item.chemical_formula}</span>', // this string will be re-used for the headline icon: '', text: '', section: '', rank: 1, headline_create: true, headline_rank: 350, },
Derived fields
Derived fields have a dependency on another field or value. These fields may or may not use some Wikidata data.
Dependent values can be all sorts of different things:
- The existance of a Wikidata-Qid for the topic.
- A topic title string like “Classical music”
- an active user language like “es” (Spanish)
- a remote JSON API call definition (eg. for the Rijksmuseum API)
- etc.
examples
example: wikidata-derived field
The derived-field example below will show a link to the “GBIF organism occurrence map”, but only if the “item.gbif_id” was set (from an earlier Wikidata field definition).
'gbif_id' : { // normal Wikidata field render_condition: false, title: 'gbif_id', prop: '846', type: '', mv: false, icon: '', text: '', section: '', rank: 1, }, 'gbif_occurence_map' : { // Derived field, which depends on the field above being set create_condition: '${ valid( item.gbif_id ) }', title: 'GBIF occurence map', prop: '', type: 'link', url: '${explore.base}/app/response/gbif-map?l=${explore.language}&t=${title_enc}&id=${item.gbif_id}', // The "explore.base" directory comes from the Conzept setting "CONZEPT_WEB_BASE", // to make the URL root location more flexible, but is not required. mv: false, icon: 'fas fa-binoculars', text: 'occurence map', section: ['science-biology','main'], rank: [400,7900], },
example: title-based external-link field
This will show a tab-opening link to Google Scholar.
'google_scholar' : { create_condition: true, title: 'Google Scholar', prop: '', type: 'url', // "url" always opens links in a new tab mv: false, url: 'https://scholar.google.com/scholar?q=${title_quoted}', icon: 'fab fa-google', text: 'Google Scholar', section: 'science-search-tools', rank: 60, },
example: language-conditioned link field
This will show the Russian Yandex search-engine link, but only if the users' language is set to Russian:
'yandex_ru' : { create_condition: 'checkLC( "ru" )', // check if the user-language is set to the Russian-language title: 'Yandex search', prop: '', type: 'url', mv: false, url: 'https://yandex.ru/search/?text=${title_quoted}', icon: 'fab fa-yandex', text: 'Yandex', section: 'web', rank: 4, },
example: API-based link field
This is an example of a field which fetches data from the Wikicommons API, using special code located in the fetch directory.
The specific code for this API can be found here.
[ Note: In the future this API-interface will likely be further specified and passed on to the API-function as a normal JS object. ]
'wikicommons_inline' : { value: 'wikicommons:${item.title}:true', // name of the API to call in the code, and the arguments which are passed to it. title: 'view wikiCommons media', render_condition: 'valid( item.qid )', // only render this link if there is a Wikidata Qid prop: '0', // Note: currently all API derived-fields must set their property-key to "0". // Doing this triggers the data to be processed similar to Wikidata data. type: 'rest-json', // this indicates the field is an API-derived field mv: true, icon: 'far fa-images', text: 'Commons', section: ['media-image'], rank: [61], },