MOBILE-4600 data: Adapt new default templates

main
Pau Ferrer Ocaña 2024-05-24 13:31:48 +02:00
parent 00fd418b84
commit a4136c3f1a
6 changed files with 165 additions and 77 deletions

View File

@ -555,6 +555,7 @@
"addon.mod_data.authorfirstname": "data",
"addon.mod_data.authorlastname": "data",
"addon.mod_data.confirmdeleterecord": "data",
"addon.mod_data.datemodified": "data",
"addon.mod_data.descending": "data",
"addon.mod_data.disapprove": "data",
"addon.mod_data.edittagsnotsupported": "local_moodlemobileapp",

View File

@ -74,7 +74,7 @@ export abstract class AddonModDataFieldPluginBaseComponent implements OnInit, On
}
/**
* Component being changed.
* @inheritdoc
*/
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if ((this.showMode || this.listMode) && changes.value) {

View File

@ -3,25 +3,32 @@
// Edit and search modal.
:host {
::ng-deep {
table {
width: 100%;
}
td {
vertical-align: top;
}
}
.addon-data-advanced-search {
padding: 16px;
width: 100%;
}
.addon-data-contents form,
.addon-data-edit-entry form,
form .addon-data-advanced-search {
background-color: var(--ion-item-background);
::ng-deep {
table {
width: 100%;
tbody {
display: block;
}
td {
vertical-align: top;
}
}
.edit-field,
.search-field {
border-bottom: 1px solid var(--stroke);
}
.has-errors {
.input-highlight,
.select-highlight,

View File

@ -16,17 +16,15 @@ $grid-column-paddings: (
--border-color: var(--stroke);
}
.addon-data-edit-entry {
.addon-data-contents {
overflow: visible;
white-space: normal;
word-break: break-word;
padding: 16px;
background-color: var(--ion-item-background);
border-bottom: 1px solid var(--border-color);
::ng-deep {
table, tbody {
table {
display: block;
}

View File

@ -9,6 +9,7 @@
"authorfirstname": "First name",
"authorlastname": "Last name",
"confirmdeleterecord": "Are you sure you want to delete this entry?",
"datemodified": "Last edited:",
"descending": "Descending",
"disapprove": "Undo approval",
"edittagsnotsupported": "Sorry, editing tags is not supported by the app.",

View File

@ -504,84 +504,165 @@ export class AddonModDataHelperProvider {
/**
* Returns the default template of a certain type.
*
* Based on Moodle function data_generate_default_template.
*
* @param type Type of template.
* @param fields List of database fields.
* @returns Template HTML.
*/
getDefaultTemplate(type: AddonModDataTemplateType, fields: AddonModDataField[]): string {
if (type == AddonModDataTemplateType.LIST_HEADER || type == AddonModDataTemplateType.LIST_FOOTER) {
return '';
protected getDefaultTemplate(type: AddonModDataTemplateType, fields: AddonModDataField[]): string {
switch (type) {
case AddonModDataTemplateType.LIST:
return this.getDefaultListTemplate(fields);
case AddonModDataTemplateType.SINGLE:
return this.getDefaultSingleTemplate(fields);
case AddonModDataTemplateType.SEARCH:
return this.getDefaultSearchTemplate(fields);
case AddonModDataTemplateType.ADD:
return this.getDefaultAddTemplate(fields);
}
return '';
}
/**
* Returns the default template for the list view.
*
* @param fields List of database fields.
* @returns Template HTML.
*/
protected getDefaultListTemplate(fields: AddonModDataField[]): string {
const html: string[] = [];
if (type == AddonModDataTemplateType.LIST) {
html.push('##delcheck##<br />');
}
html.push(`<ion-card class="defaulttemplate-listentry">
<ion-item class="ion-text-wrap" lines="full">
##userpicture##
<ion-label>
<p class="item-heading">##user##</p>
<p class="data-timeinfo">##timeadded##</p>
<p class="data-timeinfo">
<strong>${Translate.instant('addon.mod_data.datemodified')}</strong>&nbsp;##timemodified##
</p>
</ion-label>
<div slot="end" class="ion-text-end">
##actionsmenu##
<p class="ion-text-end ##approvalstatusclass##">##approvalstatus##</p>
</div>
</ion-item>
html.push(
'<div class="defaulttemplate">',
'<table class="mod-data-default-template ##approvalstatus##">',
'<tbody>',
);
<ion-item class="ion-text-wrap defaulttemplate-list-body"><ion-label>`);
fields.forEach((field) => {
html.push(
'<tr class="">',
'<td class="template-field cell c0" style="">',
field.name,
': </td>',
'<td class="template-token cell c1 lastcol" style="">[[',
field.name,
']]</td>',
'</tr>',
);
html.push(`
<ion-row class="ion-margin-vertical ion-align-items-start ion-justify-content-start">
<ion-col size="4" size-lg="3"><strong>${field.name}</strong></ion-col>
<ion-col size="8" size-lg="9">[[${field.name}]]</ion-col>
</ion-row>`);
});
if (type == AddonModDataTemplateType.LIST) {
html.push(
'<tr class="lastrow">',
'<td class="controls template-field cell c0 lastcol" style="" colspan="2">',
'##actionsmenu## ##edit## ##more## ##delete## ##approve## ##disapprove## ##export##',
'</td>',
'</tr>',
);
} else if (type == AddonModDataTemplateType.SINGLE) {
html.push(
'<tr class="lastrow">',
'<td class="controls template-field cell c0 lastcol" style="" colspan="2">',
'##actionsmenu## ##edit## ##delete## ##approve## ##disapprove## ##export##',
'</td>',
'</tr>',
);
} else if (type == AddonModDataTemplateType.SEARCH) {
html.push(
'<tr class="searchcontrols">',
'<td class="template-field cell c0" style="">Author first name: </td>',
'<td class="template-token cell c1 lastcol" style="">##firstname##</td>',
'</tr>',
'<tr class="searchcontrols lastrow">',
'<td class="template-field cell c0" style="">Author surname: </td>',
'<td class="template-token cell c1 lastcol" style="">##lastname##</td>',
'</tr>',
);
}
html.push(
'</tbody>',
'</table>',
'</div>',
);
if (type == AddonModDataTemplateType.LIST) {
html.push('<hr />');
}
html.push('##tags##</ion-label></ion-item></ion-card>');
return html.join('');
}
/**
* Returns the default template for the add view.
*
* @param fields List of database fields.
* @returns Template HTML.
*/
protected getDefaultAddTemplate(fields: AddonModDataField[]): string {
const html: string[] = [];
html.push('<div class="defaulttemplate-addentry">');
fields.forEach((field) => {
html.push(`
<div class="ion-text-wrap edit-field">
<p><strong>${field.name}</strong></p>
[[${field.name}]]
</div>`);
});
html.push('##otherfields## ##tags##</div>');
return html.join('');
}
/**
* Returns the default template for the single view.
*
* @param fields List of database fields.
* @returns Template HTML.
*/
protected getDefaultSingleTemplate(fields: AddonModDataField[]): string {
const html: string[] = [];
html.push(`<div class="defaulttemplate-single">
<div class="defaulttemplate-single-body">
<ion-item class="ion-text-wrap" lines="full">
##userpicture##
<ion-label>
<p class="item-heading">##user##</p>
<p class="data-timeinfo">##timeadded##</p>
<p class="data-timeinfo">
<strong>${Translate.instant('addon.mod_data.datemodified')}</strong>&nbsp;##timemodified##
</p>
</ion-label>
<div slot="end" class="ion-text-end">
##actionsmenu##
<p class="ion-text-end ##approvalstatusclass##">##approvalstatus##</p>
</div>
</ion-item>`);
fields.forEach((field) => {
html.push(`
<ion-item class="ion-text-wrap" lines="none"><ion-label>
<p class="item-heading"><strong>${field.name}</strong></p>
<p>[[${field.name}]]</p>
</ion-label></ion-item>`);
});
html.push('##otherfields## ##tags##</ion-label></ion-item></div></div>');
return html.join('');
}
/**
* Returns the default template for the search view.
*
* @param fields List of database fields.
* @returns Template HTML.
*/
protected getDefaultSearchTemplate(fields: AddonModDataField[]): string {
const html: string[] = [];
html.push('<div class="defaulttemplate-asearch">');
html.push(`
<div class="ion-text-wrap search-field">
<p><strong>${Translate.instant('addon.mod_data.authorfirstname')}</strong></p>
##firstname##
</div>`);
html.push(`
<div class="ion-text-wrap search-field">
<p><strong>${Translate.instant('addon.mod_data.authorlastname')}</strong></p>
##lastname##
</div>`);
fields.forEach((field) => {
html.push(`
<div class="ion-text-wrap search-field">
<p><strong>${field.name}</strong></p>
[[${field.name}]]
</div>`);
});
html.push('##tags##</div>');
return html.join('');
}
/**
* Retrieve the entered data in the edit form.
* We don't use ng-model because it doesn't detect changes done by JavaScript.