Skip to content

Commit 437abb1

Browse files
Hasan Akgünjenkins-bot
authored andcommitted
Add references edit form to edit statements
Bug: T402433 Change-Id: I109f27494485cfec68737f9c14c8f67dfaa6b791
1 parent 339c128 commit 437abb1

File tree

11 files changed

+457
-4
lines changed

11 files changed

+457
-4
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { Util } from 'cypress-wikibase-api';
2+
3+
import { ItemViewPage } from '../../support/pageObjects/ItemViewPage';
4+
import { EditStatementFormPage } from '../../support/pageObjects/EditStatementFormPage';
5+
import { AddReferenceFormPage } from '../../support/pageObjects/AddReferenceFormPage';
6+
7+
describe( 'wbui2025 add reference', () => {
8+
context( 'mobile view', () => {
9+
let itemViewPage: ItemViewPage;
10+
beforeEach( () => {
11+
cy.task( 'MwApi:GetOrCreatePropertyIdByDataType', { datatype: 'string' } )
12+
.then( ( propertyId: string ) => {
13+
cy.wrap( propertyId ).as( 'propertyId' );
14+
const statementData = {
15+
claims: [ {
16+
mainsnak: {
17+
snaktype: 'value',
18+
property: propertyId,
19+
datavalue: {
20+
value: 'example string value',
21+
type: 'string',
22+
},
23+
},
24+
type: 'statement',
25+
rank: 'normal',
26+
} ],
27+
};
28+
cy.task( 'MwApi:CreateItem', { label: Util.getTestString( 'item' ), data: statementData } )
29+
.then( ( itemId: string ) => {
30+
itemViewPage = new ItemViewPage( itemId );
31+
} );
32+
} );
33+
cy.viewport( 375, 1280 );
34+
} );
35+
36+
it( 'is possible to add a reference', () => {
37+
itemViewPage.open();
38+
itemViewPage.editLinks().first().click();
39+
const editStatementFormPage = new EditStatementFormPage();
40+
editStatementFormPage.addReferenceButton().click();
41+
const addReferenceFormPage = new AddReferenceFormPage();
42+
addReferenceFormPage.heading().should( 'have.text', 'add reference' );
43+
44+
// Before a property is selected
45+
addReferenceFormPage.addButton().should( 'be.disabled' );
46+
addReferenceFormPage.snakValueInput().should( 'not.exist' );
47+
48+
cy.get( '@propertyId' ).then( ( propertyId ) => {
49+
addReferenceFormPage.setProperty( propertyId );
50+
} );
51+
const referenceSnakValue = Util.getTestString( 'referenceSnak' );
52+
addReferenceFormPage.setSnakValue( referenceSnakValue );
53+
addReferenceFormPage.addButton().click();
54+
55+
editStatementFormPage.valueForms().should( 'contain.text', referenceSnakValue );
56+
editStatementFormPage.publishButton().click();
57+
editStatementFormPage.form().should( 'not.exist' );
58+
59+
itemViewPage.referencesSections().first().then( ( element ) => {
60+
itemViewPage.referencesAccordion( element ).click();
61+
itemViewPage.references( element ).should( 'contain.text', referenceSnakValue );
62+
} );
63+
} );
64+
} );
65+
} );
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import Chainable = Cypress.Chainable;
2+
3+
export class AddReferenceFormPage {
4+
public static SELECTORS = {
5+
HEADING: '.wikibase-wbui2025-add-reference-heading h2',
6+
PROPERTY_INPUT: '.wikibase-wbui2025-property-lookup input',
7+
SNAK_VALUE_INPUT: '.wikibase-wbui2025-add-reference-value input',
8+
ADD_BUTTON: '.wikibase-wbui2025-add-reference-form .cdx-button',
9+
PROPERTY_OPTIONS: '.wikibase-wbui2025-property-lookup .cdx-menu-item',
10+
};
11+
12+
public heading(): Chainable {
13+
return cy.get( AddReferenceFormPage.SELECTORS.HEADING );
14+
}
15+
16+
public propertyInput(): Chainable {
17+
return cy.get( AddReferenceFormPage.SELECTORS.PROPERTY_INPUT );
18+
}
19+
20+
public snakValueInput(): Chainable {
21+
return cy.get( AddReferenceFormPage.SELECTORS.SNAK_VALUE_INPUT );
22+
}
23+
24+
public addButton(): Chainable {
25+
return cy.get( AddReferenceFormPage.SELECTORS.ADD_BUTTON );
26+
}
27+
28+
public setProperty( searchTerm: string ): this {
29+
this.propertyInput().type( searchTerm );
30+
cy.get( AddReferenceFormPage.SELECTORS.PROPERTY_OPTIONS ).first().click();
31+
return this;
32+
}
33+
34+
public setSnakValue( inputText: string ): this {
35+
this.snakValueInput().type( inputText );
36+
return this;
37+
}
38+
}

cypress/support/pageObjects/EditStatementFormPage.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Chainable = Cypress.Chainable;
33
export class EditStatementFormPage {
44

55
public static SELECTORS = {
6+
FORM: '.wikibase-wbui2025-edit-statement',
67
PROPERTY_NAME: '.wikibase-wbui2025-property-name > a',
78
REMOVE_VALUE_BUTTONS: '.wikibase-wbui2025-remove-value > .cdx-button',
89
ADD_VALUE_BUTTONS: '.wikibase-wbui2025-add-value > .cdx-button',
@@ -14,6 +15,7 @@ export class EditStatementFormPage {
1415
MENU: '.wikibase-wbui2025-edit-statement-value-input .cdx-menu',
1516
MENU_ITEM: '.wikibase-wbui2025-edit-statement-value-input .cdx-menu-item',
1617
RANK_SELECT: '.wikibase-wbui2025-rank-input .cdx-select-vue',
18+
ADD_REFERENCE_BUTTON: '.wikibase-wbui2025-add-reference-button',
1719
};
1820

1921
public static FORM_HEADING = '.wikibase-wbui2025-edit-statement-heading';
@@ -89,4 +91,12 @@ export class EditStatementFormPage {
8991
public getLookupInputSelector(): string {
9092
return EditStatementFormPage.SELECTORS.LOOKUP_INPUT;
9193
}
94+
95+
public addReferenceButton(): Chainable {
96+
return cy.get( EditStatementFormPage.SELECTORS.ADD_REFERENCE_BUTTON );
97+
}
98+
99+
public form(): Chainable {
100+
return cy.get( EditStatementFormPage.SELECTORS.FORM );
101+
}
92102
}

cypress/support/pageObjects/ItemViewPage.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export class ItemViewPage {
1616

1717
public static REFERENCES_SECTION = '.wikibase-wbui2025-references';
1818

19+
public static REFERENCES_ACCORDION = '.wikibase-wbui2025-clickable';
20+
1921
public static REFERENCES = '.wikibase-wbui2025-reference';
2022

2123
public static MAIN_SNAKS = '.wikibase-wbui2025-main-snak';
@@ -62,6 +64,10 @@ export class ItemViewPage {
6264
return cy.get( ItemViewPage.REFERENCES_SECTION );
6365
}
6466

67+
public referencesAccordion( context: HTMLElement ): Chainable {
68+
return cy.get( ItemViewPage.REFERENCES_ACCORDION, { withinSubject: context } );
69+
}
70+
6571
public references( context: HTMLElement ): Chainable {
6672
return cy.get( ItemViewPage.REFERENCES, { withinSubject: context } );
6773
}

repo/includes/RepoHooks.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,7 @@ public function onResourceLoaderRegisterModules( $rl ): void {
996996
'resources/wikibase.wbui2025/wikibase.wbui2025.propertyName.vue',
997997
'resources/wikibase.wbui2025/wikibase.wbui2025.addStatementButton.vue',
998998
'resources/wikibase.wbui2025/wikibase.wbui2025.addQualifier.vue',
999+
'resources/wikibase.wbui2025/wikibase.wbui2025.addReference.vue',
9991000
'resources/wikibase.wbui2025/wikibase.wbui2025.propertyLookup.vue',
10001001
'resources/wikibase.wbui2025/wikibase.wbui2025.propertySelector.vue',
10011002
'resources/wikibase.wbui2025/wikibase.wbui2025.modalOverlay.vue',

repo/resources/wikibase.wbui2025/store/savedStatementsStore.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,28 @@ const useSavedStatementsStore = defineStore( 'savedStatements', {
2929
}
3030
}
3131
}
32+
if ( statement.references ) {
33+
for ( const reference of statement.references ) {
34+
const snaks = reference.snaks;
35+
if ( !snaks || typeof snaks !== 'object' ) {
36+
continue;
37+
}
38+
39+
for ( const referenceSnak in reference.snaks ) {
40+
const list = snaks[ referenceSnak ];
41+
if ( !list.length ) {
42+
continue;
43+
}
44+
45+
for ( const snak of reference.snaks[ referenceSnak ] ) {
46+
if ( 'hash' in snak && !snakValueHtmlForHash( snak.hash ) ) {
47+
snaksWithoutHtml.push( snak );
48+
}
49+
}
50+
}
51+
}
52+
}
53+
3254
}
3355
this.properties.set( propertyId, statementIdList );
3456
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<template>
2+
<wikibase-wbui2025-modal-overlay>
3+
<div class="wikibase-wbui2025-add-reference">
4+
<div class="wikibase-wbui2025-add-reference-heading">
5+
<div class="wikibase-wbui2025-add-reference-close">
6+
<cdx-button
7+
:aria-label="$i18n( 'wikibase-cancel' )"
8+
weight="quiet"
9+
@click="$emit( 'hide' )"
10+
>
11+
<cdx-icon :icon="cdxIconClose"></cdx-icon>
12+
</cdx-button>
13+
</div>
14+
<h2>{{ $i18n( 'wikibase-addreference' ) }}</h2>
15+
</div>
16+
<div class="wikibase-wbui2025-add-reference-form">
17+
<cdx-button
18+
action="progressive"
19+
:disabled="addButtonDisabled"
20+
@click="$emit( 'add-reference', selectedPropertyId, snakData )"
21+
>
22+
<cdx-icon :icon="cdxIconCheck"></cdx-icon>
23+
{{ $i18n( 'wikibase-add' ) }}
24+
</cdx-button>
25+
<wikibase-wbui2025-property-lookup
26+
ref="propertyLookup"
27+
@update:selected="onPropertySelection"
28+
>
29+
</wikibase-wbui2025-property-lookup>
30+
<cdx-text-input
31+
v-if="selectedPropertyDatatype === 'string'"
32+
ref="textInput"
33+
v-model.trim="snakValue"
34+
class="wikibase-wbui2025-add-reference-value"
35+
:placeholder="$i18n( 'wikibase-addreference' ).text()"
36+
>
37+
</cdx-text-input>
38+
</div>
39+
</div>
40+
</wikibase-wbui2025-modal-overlay>
41+
</template>
42+
43+
<script>
44+
const { defineComponent, nextTick } = require( 'vue' );
45+
const { CdxButton, CdxIcon, CdxTextInput } = require( '../../codex.js' );
46+
const { cdxIconClose, cdxIconCheck } = require( './icons.json' );
47+
48+
const WikibaseWbui2025ModalOverlay = require( './wikibase.wbui2025.modalOverlay.vue' );
49+
const WikibaseWbui2025PropertyLookup = require( './wikibase.wbui2025.propertyLookup.vue' );
50+
51+
module.exports = exports = defineComponent( {
52+
name: 'WikibaseWbui2025AddReference',
53+
components: {
54+
CdxButton,
55+
CdxIcon,
56+
CdxTextInput,
57+
WikibaseWbui2025ModalOverlay,
58+
WikibaseWbui2025PropertyLookup
59+
},
60+
emits: [ 'hide', 'add-reference' ],
61+
data() {
62+
return {
63+
cdxIconClose,
64+
cdxIconCheck,
65+
selectedPropertyId: null,
66+
selectedPropertyDatatype: null,
67+
snakValue: ''
68+
};
69+
},
70+
computed: {
71+
addButtonDisabled() {
72+
return !( this.selectedPropertyId && this.snakValue );
73+
},
74+
snakData() {
75+
return {
76+
snaktype: 'value',
77+
property: this.selectedPropertyId,
78+
datavalue: {
79+
value: this.snakValue,
80+
type: this.selectedPropertyDatatype
81+
},
82+
datatype: this.selectedPropertyDatatype
83+
};
84+
}
85+
},
86+
methods: {
87+
onPropertySelection( propertyId, propertyData ) {
88+
this.selectedPropertyId = propertyId;
89+
this.selectedPropertyDatatype = propertyData.datatype;
90+
nextTick( () => {
91+
this.$refs.textInput.focus();
92+
} );
93+
}
94+
},
95+
mounted() {
96+
nextTick( () => {
97+
this.$refs.propertyLookup.focus();
98+
} );
99+
}
100+
} );
101+
</script>
102+
103+
<style lang="less">
104+
@import 'mediawiki.skin.variables.less';
105+
106+
.wikibase-wbui2025-add-reference {
107+
display: flex;
108+
flex-direction: column;
109+
align-items: flex-start;
110+
gap: @spacing-65;
111+
width: 100%;
112+
height: 100%;
113+
}
114+
115+
.wikibase-wbui2025-add-reference-heading {
116+
align-self: stretch;
117+
padding: @spacing-100 @spacing-100 @spacing-200;
118+
border-bottom: @border-width-base @border-style-base @border-color-subtle;
119+
120+
h2 {
121+
padding: @spacing-0;
122+
font-family: @font-family-base;
123+
text-align: center;
124+
color: @color-emphasized;
125+
}
126+
}
127+
128+
.wikibase-wbui2025-add-reference-close {
129+
text-align: right;
130+
}
131+
132+
.wikibase-wbui2025-add-reference-form {
133+
padding: @spacing-200 @spacing-100;
134+
align-self: stretch;
135+
display: flex;
136+
flex-direction: column;
137+
gap: @spacing-150;
138+
align-items: flex-end;
139+
}
140+
141+
.wikibase-wbui2025-add-reference-value {
142+
align-self: stretch;
143+
}
144+
</style>

0 commit comments

Comments
 (0)