Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5990528
NukeNamespaceLookup.vue
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
NukeNamespaceLookup.vue
View Options
<template>
<cdx-field :status="status" :messages="messages">
<cdx-multiselect-lookup
id="nuke-namespace-lookup"
v-model:input-chips="chips"
v-model:selected="selection"
v-model:input-value="inputValue"
:menu-items="menuItems"
:menu-config="menuConfig"
:placeholder="$i18n( 'mw-widgets-titlesmultiselect-placeholder' ).text()"
@input="onInput"
@update:selected="onSelection"
@blur="validateInstantly"
@keydown.enter="validateInstantly"
></cdx-multiselect-lookup>
<template #label>
{{ $i18n( 'nuke-namespace' ).text() }}
</template>
</cdx-field>
<textarea
class="ext-nuke-form-hidden"
name="namespace"
:value="chips.map( chip => chip.value ).join( '\n' )"></textarea>
</template>
<script>
// `mediawiki.api` does not have exports. Instead, it sets the `mw.Api` global.
require( 'mediawiki.api' );
const { defineComponent, onMounted, ref, nextTick } = require( 'vue' );
const { CdxField, CdxMultiselectLookup } = require( '../codex.js' );
module.exports = exports = defineComponent( {
name: 'NukeNamespaceLookup',
components: {
CdxField, CdxMultiselectLookup
},
props: {
namespaces: {
type: String,
required: false,
default: ''
}
},
setup( props ) {
const chips = ref( [] );
const selection = ref( [] );
const inputValue = ref( '' );
const namespaces = ref( [] );
const menuItems = ref( [] );
const menuConfig = {
visibleItemLimit: 6
};
const status = ref( 'default' );
const messages = {
warning: mw.msg( 'nuke-namespace-invalid' ),
error: mw.msg( 'nuke-namespace-invalid' )
};
/**
* Maybe set a warning message when the user moves out of the field or hits enter.
*/
function validateInstantly() {
// Await nextTick in case the user has selected a menu item via the Enter key - this
// will ensure the selection ref has been updated.
nextTick( () => {
// Set warning status if there's input. This might happen if a user types something
// but doesn't select an item from the menu.
status.value = inputValue.value.length > 0 ? 'warning' : 'default';
} );
}
/**
* Clear warning or error after a selection is made.
*/
function onSelection() {
if ( selection.value !== null ) {
status.value = 'default';
}
}
/**
* Handle lookup input.
*
* @param {string} value The new input value
*/
function onInput( value ) {
// Reset menu items if the input was cleared.
if ( !value ) {
menuItems.value = namespaces.value;
return;
}
// Make sure this data is still relevant first.
if ( inputValue.value !== value ) {
return;
}
// Update menuItems.
menuItems.value = namespaces.value.filter(
( namespace ) => namespace.label
.toLocaleLowerCase()
.includes( value.toLocaleLowerCase() )
);
}
/**
* Get a list of namespaces.
*
* @return {Promise}
*/
function getNamespaces() {
return ( new mw.Api() ).get( {
action: 'query',
meta: 'siteinfo',
siprop: 'namespaces'
} );
}
function formatData( namespaceData ) {
const formattedData = [
// Main namespace
{
value: 0,
label: mw.msg( 'blanknamespace' )
}
];
for ( const namespaceId of Object.keys( namespaceData ) ) {
// Only select namespaces that have an ID > 0.
// This will exclude the main namespace, and any virtual namespaces we have.
if ( 'canonical' in namespaceData[ namespaceId ] && +namespaceId > 0 ) {
formattedData.push( {
value: parseInt( namespaceId ),
label: namespaceData[ namespaceId ].canonical
} );
}
}
return formattedData;
}
onMounted( () => {
getNamespaces()
.then( ( data ) => {
// Store formatted namespaces.
namespaces.value = formatData( data.query.namespaces );
// Set initial menu items.
menuItems.value = namespaces.value;
// Select namespaces based on existing input data.
const selectedNamespaces = props.namespaces.split( '\n' )
.map( ( namespaceId ) => parseInt( namespaceId.trim() ) );
chips.value = namespaces.value.filter(
( namespace ) => selectedNamespaces.includes( namespace.value )
);
selection.value = chips.value.map( ( v ) => v.value );
} );
} );
return {
chips,
selection,
inputValue,
menuItems,
menuConfig,
status,
messages,
validateInstantly,
onSelection,
onInput
};
}
} );
</script>
File Metadata
Details
Attached
Mime Type
text/html
Expires
Sun, Oct 4, 01:33 (3 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
9d/ad/62524fc5cfe60b07c26c8a018180
Default Alt Text
NukeNamespaceLookup.vue (4 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment