Merge pull request #2761 from crazyserver/MOBILE-3320

MOBILE-3320 lang: Use AWS to update lang files
main
Noel De Martin 2021-05-13 12:23:55 +02:00 committed by GitHub
commit 8c16e648c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 279 additions and 82 deletions

View File

@ -15,14 +15,21 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm ci
- run: git clone --branch master --depth 1 git://github.com/moodle/moodle $GITHUB_WORKSPACE/moodle
- run: git clone --branch ionic5 --depth 1 git://github.com/moodlehq/moodle-local_moodlemobileapp $GITHUB_WORKSPACE/moodle/local/moodlemobileapp
- run: git clone --branch MOBILE-3738 --depth 1 git://github.com/NoelDeMartin/moodle-docker $GITHUB_WORKSPACE/moodle-docker
- run: cp $GITHUB_WORKSPACE/moodle-docker/config.docker-template.php $GITHUB_WORKSPACE/moodle/config.php
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose pull
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose up -d
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-wait-for-db
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-wait-for-app
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose exec -T webserver sh -c "php admin/tool/behat/cli/init.php"
- run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose exec -T webserver sh -c "php admin/tool/behat/cli/run.php --tags="@app" --auto-rerun"
- name: Install npm packages
run: npm ci
- name: Additional checkouts
run: |
git clone --branch master --depth 1 git://github.com/moodle/moodle $GITHUB_WORKSPACE/moodle
git clone --branch ionic5 --depth 1 git://github.com/moodlehq/moodle-local_moodlemobileapp $GITHUB_WORKSPACE/moodle/local/moodlemobileapp
git clone --branch MOBILE-3738 --depth 1 git://github.com/NoelDeMartin/moodle-docker $GITHUB_WORKSPACE/moodle-docker
- name: Setup docker machine
run: |
cp $GITHUB_WORKSPACE/moodle-docker/config.docker-template.php $GITHUB_WORKSPACE/moodle/config.php
MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose pull
MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose up -d
MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-wait-for-db
MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-wait-for-app
- name: Init behat
run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose exec -T webserver sh -c "php admin/tool/behat/cli/init.php"
- name: Run tests
run: MOODLE_DOCKER_WWWROOT=$GITHUB_WORKSPACE/moodle MOODLE_DOCKER_APP_PATH=$GITHUB_WORKSPACE $GITHUB_WORKSPACE/moodle-docker/bin/moodle-docker-compose exec -T webserver sh -c "php admin/tool/behat/cli/run.php --tags="@app" --auto-rerun"

View File

@ -13,8 +13,45 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm ci
- run: npm run lint
- run: npm run test:ci
- run: npm run build:prod
- run: result=$(npx check-es-compat www/*.js 2> /dev/null | grep -v -E "Array\.prototype\.includes|Promise\.prototype\.finally|String\.prototype\.(matchAll|trimRight)|globalThis" | grep -Po "(?<=error).*?(?=\s+ecmascript)" | wc -l); test $result -eq 0
- name: Install npm packages
run: npm ci
- name: Check langindex
run: |
result=$(cat scripts/langindex.json | grep \"TBD\" | wc -l); test $result -eq 0
if [ $result -ne 0 ]; then
echo "There are lang strings to be decided on langindex.json"
exit 1
fi
gulp
langlength=`jq -r '. | length' src/assets/lang/en.json`
langindexlength=`jq -r '. | length' scripts/langindex.json`
if [ $langlength -ne $langindexlength ]; then
echo "Lang file has $langlength while langindex $langindexlength"
exit 1
fi
langkeys=`jq -r 'keys[]' src/assets/lang/en.json`
langindex=`jq -r 'keys[]' scripts/langindex.json`
found=0
for i in $langkeys; do
skip=
for j in $langindex; do
if [ "$i" == "$j" ]; then
skip=1
break;
fi
done
[[ -n $skip ]] || { echo "$i key not found"; found=$(($found + 1)); }
done
if [ $found -ne 0 ]; then
echo "Found $found missing langkeys"
exit 1
fi
- name: Run Linter
run: npm run lint
- name: Run tests
run: npm run test:ci
- name: Production builds
run: npm run build:prod
- name: JavaScript code compatibility
run: result=$(npx check-es-compat www/*.js 2> /dev/null | grep -v -E "Array\.prototype\.includes|Promise\.prototype\.finally|String\.prototype\.(matchAll|trimRight)|globalThis" | grep -Po "(?<=error).*?(?=\s+ecmascript)" | wc -l); test $result -eq 0

View File

@ -1,5 +1,12 @@
#!/bin/bash
#
# Script to create langindex from available language packs.
# ./create_langindex.sh [findbetter]
# If findbetter is set it will try to find a better solution for every key.
#
source "functions.sh"
source "lang_functions.sh"
#Saves or updates a key on langindex_old.json
function save_key {
@ -48,7 +55,8 @@ function exists_in_mobile {
}
function do_match {
match=$1
match=${1/\{\{/\{}
match=${match/\}\}/\}}
filematch=""
coincidence=`grep "$match" $LANGPACKSFOLDER/en/*.php | wc -l`
@ -56,7 +64,7 @@ function do_match {
filematch=`grep "$match" $LANGPACKSFOLDER/en/*.php | cut -d'/' -f5 | cut -d'.' -f1`
exists_in_file $filematch $plainid
elif [ $coincidence -gt 0 ] && [ "$#" -gt 1 ]; then
print_message $2
print_message "$2"
tput setaf 6
grep "$match" $LANGPACKSFOLDER/en/*.php
fi
@ -67,18 +75,21 @@ function find_matches {
do_match "string\[\'$plainid\'\] = \'$value\'" "Found EXACT match for $key in the following paths"
if [ $coincidence -gt 0 ]; then
case=1
save_key $key "TBD"
return
fi
do_match " = \'$value\'" "Found some string VALUES for $key in the following paths"
if [ $coincidence -gt 0 ]; then
case=2
save_key $key "TBD"
return
fi
do_match "string\[\'$plainid\'\]" "Found some string KEYS for $key in the following paths, value $value"
if [ $coincidence -gt 0 ]; then
case=3
save_key $key "TBD"
return
fi
@ -297,17 +308,13 @@ function array_contains {
done
}
print_title 'Generating language from code...'
gulp lang
print_title 'Getting languages'
git clone https://git.in.moodle.com/moodle/moodle-langpacks.git $LANGPACKSFOLDER
pushd $LANGPACKSFOLDER
BRANCHES=($(git branch -r --format="%(refname:lstrip=3)" --sort="refname" | grep MOODLE_))
BRANCH=${BRANCHES[${#BRANCHES[@]}-1]}
git checkout $BRANCH
git pull
popd
get_language en
print_title 'Processing file'
#Create langindex.json if not exists.

View File

@ -1,7 +1,5 @@
#!/bin/bash
LANGPACKSFOLDER='../../moodle-langpacks'
function check_success_exit {
if [ $? -ne 0 ]; then
print_error "$1"

View File

@ -0,0 +1,132 @@
#!/bin/bash
#
# Functions to fetch languages.
#
LANGPACKSFOLDER='../../moodle-langpacks'
BUCKET='moodle-lang-prod'
MOODLEORG_URL='https://download.moodle.org/download.php/direct/langpack'
DEFAULT_LASTVERSION='4.0'
# Checks if AWS is available and configured.
function check_aws {
aws --version &> /dev/null
AWS_SERVICE=1
if [ $? -ne 0 ]; then
AWS_SERVICE=0
echo 'AWS not installed. Check https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html for more info.'
return
fi
# In order to login to AWS, use credentials file or AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY vars.
if [ ! -f ~/.aws/credentials ] && [ [ -z $AWS_ACCESS_KEY_ID ] || [ -z $AWS_SECRET_ACCESS_KEY ] ]; then
AWS_SERVICE=0
lastversion=$DEFAULT_LASTVERSION
echo 'AWS Cannot authenticate. Use aws configure or set the proper env vars.'
return
fi
}
# Get last version of Moodle to fetch latest languages.
function get_last_version {
if [ ! -z "${lastversion}" ]; then
return
fi
check_aws
if [ $AWS_SERVICE -eq 0 ]; then
lastversion=$DEFAULT_LASTVERSION
echo "Using default version $lastversion"
return
fi
list=`aws s3 ls s3://$BUCKET/`
if [ $? -ne 0 ]; then
AWS_SERVICE=0
lastversion=$DEFAULT_LASTVERSION
echo "AWS Cannot authenticate. Using default version $lastversion"
return
fi
lastversion=''
for folder in $list; do
if [ $folder != 'PRE' ]; then
lastversion=${folder/\//}
fi
done
if [ ! -z "${lastversion}" ]; then
echo "Last version $lastversion detected"
return
fi
lastversion=$DEFAULT_LASTVERSION
}
# Get all language list from AWS.
function get_all_languages_aws {
langsfiles=`aws s3 ls s3://$BUCKET/$lastversion/`
langs=""
for file in $langsfiles; do
if [[ "$file" == *.zip ]]; then
file=${file/\.zip/}
langs+="$file "
fi
done
}
# Get language list from the installed ones (will not discover new translations).
function get_installed_languages {
langs=`jq -r '.languages | keys[]' ../moodle.config.json`
}
# Entry function to get a language file.
function get_language {
lang=$1
lang=${lang/-/_}
get_last_version
echo "Getting $lang language"
pushd $LANGPACKSFOLDER > /dev/null
curl -s $MOODLEORG_URL/$lastversion/$lang.zip --output $lang.zip > /dev/null
rm -R $lang
unzip -o -u $lang.zip > /dev/null
# This is the AWS version to get the language but right now it's slower.
# aws s3 cp s3://$BUCKET/$lastversion/$lang.zip . > /dev/null
rm $lang.zip
popd > /dev/null
}
# Entry function to get all language files.
function get_languages {
get_last_version
if [ -d $LANGPACKSFOLDER ]; then
lastupdate=`date -r $LANGPACKSFOLDER +%s`
currenttime=`date +%s`
ellapsedtime=$((currenttime - lastupdate))
if [ $ellapsedtime -lt 3600 ]; then
echo 'Recently updated, skip update languages'
return
fi
else
mkdir $LANGPACKSFOLDER
fi
if [ $AWS_SERVICE -eq 1 ]; then
get_all_languages_aws
else
echo "Fallback language list will only get current installation languages"
get_installed_languages
fi
for lang in $langs; do
get_language "$lang"
done
}

View File

@ -1,23 +1,23 @@
#!/bin/bash
#
# Script to update language packs on assets and detect new translated languages.
# ./update_lang.sh [language]
# If language is set it will only update the selected language.
#
source "functions.sh"
forceLang=$1
source "lang_functions.sh"
print_title 'Getting languages'
git clone --depth 1 --no-single-branch https://git.in.moodle.com/moodle/moodle-langpacks.git $LANGPACKSFOLDER
pushd $LANGPACKSFOLDER
BRANCHES=($(git branch -r --format="%(refname:lstrip=3)" --sort="refname" | grep MOODLE_))
BRANCH=${BRANCHES[${#BRANCHES[@]}-1]}
git checkout $BRANCH
git pull
popd
forceLang=$1
print_title 'Getting local mobile langs'
git clone --depth 1 https://github.com/moodlehq/moodle-local_moodlemobileapp.git ../../moodle-local_moodlemobileapp
if [ -z $forceLang ]; then
get_languages
php -f moodle_to_json.php
else
get_language "$forceLang"
php -f moodle_to_json.php "$forceLang"
fi
print_ok 'All done!'
print_ok 'All done!'

View File

@ -74,7 +74,7 @@
</ion-searchbar>
<core-empty-box *ngIf="filteredCourses.length == 0" image="assets/img/icons/courses.svg"
[message]="'addon.block_myoverview.nocourses' | translate" class="core-empty-inline">
[message]="'addon.block_myoverview.nocourses' | translate" inline="true">
</core-empty-box>
<!-- List of courses. -->

View File

@ -20,7 +20,7 @@
</core-format-text>
</p>
<ion-button fill="clear" class="ion-hide-md-up" (click)="action($event, event.action.url)"
<ion-button fill="clear" class="ion-hide-md-up ion-text-wrap" (click)="action($event, event.action.url)"
[title]="event.action.name" [disabled]="!event.action.actionable" *ngIf="event.action">
{{event.action.name}}
<ion-badge slot="end" class="ion-margin-start" *ngIf="event.action.showitemcount">{{event.action.itemcount}}
@ -28,19 +28,23 @@
</ion-button>
</ion-label>
<ion-grid slot="end">
<ion-row class="ion-justify-content-end">
<div slot="end" class="events-info">
<div>
<ion-badge color="light">{{event.timesort * 1000 | coreFormatDate:"strftimetime24" }}</ion-badge>
</ion-row>
<ion-row class="ion-justify-content-end">
<ion-button fill="clear" class="ion-hide-md-down" (click)="action($event, event.action.url)"
[title]="event.action.name" [disabled]="!event.action.actionable" *ngIf="event.action">
{{event.action.name}}
<ion-badge slot="end" class="ion-margin-start" *ngIf="event.action.showitemcount">{{event.action.itemcount}}
</ion-badge>
</ion-button>
</ion-row>
</ion-grid>
</div>
<ion-button
class="ion-hide-md-down"
fill="clear"
(click)="action($event, event.action.url)"
[title]="event.action.name"
[disabled]="!event.action.actionable" *ngIf="event.action"
>
{{event.action.name}}
<ion-badge slot="end" class="ion-margin-start" *ngIf="event.action.showitemcount">
{{event.action.itemcount}}
</ion-badge>
</ion-button>
</div>
</ion-item>
</ng-container>
</ion-item-group>
@ -54,4 +58,5 @@
</div>
<core-empty-box *ngIf="empty" image="assets/img/icons/activities.svg" [message]="'addon.block_timeline.noevents' | translate"
[inline]="!showCourse"></core-empty-box>
inline="true">
</core-empty-box>

View File

@ -0,0 +1,6 @@
.events-info {
display: flex;
flex-direction: column;
text-align: end;
padding: 10px 0;
}

View File

@ -29,6 +29,7 @@ import { AddonCalendarEvent } from '@addons/calendar/services/calendar';
@Component({
selector: 'addon-block-timeline-events',
templateUrl: 'addon-block-timeline-events.html',
styleUrls: ['events.scss'],
})
export class AddonBlockTimelineEventsComponent implements OnChanges {

View File

@ -103,7 +103,7 @@ export class AddonBlockTimelineProvider {
async getActionEventsByCourses(
courseIds: number[],
siteId?: string,
): Promise<{[courseId: string]: { events: AddonCalendarEvent[]; canLoadMore: number } }> {
): Promise<{[courseId: string]: { events: AddonCalendarEvent[]; canLoadMore?: number } }> {
const site = await CoreSites.getSite(siteId);
const time = moment().subtract(14, 'days').unix(); // Check two weeks ago.
@ -123,17 +123,13 @@ export class AddonBlockTimelineProvider {
preSets,
);
if (events && events.groupedbycourse) {
const courseEvents = {};
const courseEvents: {[courseId: string]: { events: AddonCalendarEvent[]; canLoadMore?: number } } = {};
events.groupedbycourse.forEach((course) => {
courseEvents[course.courseid] = this.treatCourseEvents(course, time);
});
events.groupedbycourse.forEach((course) => {
courseEvents[course.courseid] = this.treatCourseEvents(course, time);
});
return courseEvents;
}
throw new CoreError('No events returned on core_calendar_get_action_events_by_courses.');
return courseEvents;
}
/**

View File

@ -83,7 +83,7 @@
contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
</core-format-text>
<core-empty-box *ngIf="!pageContent" icon="fas-file-alt" [message]="'addon.mod_wiki.nocontent' | translate"
[inline]="true">
inline="true">
</core-empty-box>
</article>

View File

@ -5,4 +5,6 @@
align-items: center;
justify-content: space-around;
align-content: center;
min-height: var(--a11y-min-target-size);
min-width: var(--a11y-min-target-size);
}

View File

@ -37,7 +37,7 @@ export class CoreEmptyBoxComponent {
* If this has to be shown inline instead of occupying whole page.
* If image or icon is not supplied, it's true by default.
*/
@Input() inline?: boolean;
@Input() flipIconRtl?: boolean; // Whether to flip the icon in RTL. Defaults to false.
@Input() inline = false;
@Input() flipIconRtl = false; // Whether to flip the icon in RTL. Defaults to false.
}

View File

@ -1,5 +1,5 @@
:host {
--tabs-background: var(--background);
--tabs-background: var(--core-tabs-background);
--tabs-color: var(--color);
height: 100%;
display: block;

View File

@ -1,6 +1,7 @@
:host {
position: relative;
display: block;
background: var(--background);
ion-item-divider {
min-height: 60px;

View File

@ -17,7 +17,7 @@
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
<div *ngIf="displaySectionSelector && sections && hasSeveralSections"
class="ion-text-wrap clearfix ion-justify-content-between core-button-selector-row"
class="ion-text-wrap ion-justify-content-between ion-align-items-center core-button-selector-row"
[class.core-section-download]="downloadEnabled">
<core-combobox [modalOptions]="sectionSelectorModalOptions" interface="modal" listboxId="core-course-section-button"
icon="fas-folder" [label]="'core.course.section' | translate" (onChange)="sectionChanged($event)">
@ -122,8 +122,6 @@
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
</core-format-text>
</h2>
<!-- Section download. -->
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: section}"></ng-container>
<p *ngIf="section.visible === 0 || section.availabilityinfo">
<ion-badge color="info" *ngIf="section.visible === 0 && section.uservisible !== false" class="ion-text-wrap">
{{ 'core.course.hiddenfromstudents' | translate }}
@ -137,6 +135,8 @@
</ion-badge>
</p>
</ion-label>
<!-- Section download. -->
<ng-container *ngTemplateOutlet="sectionDownloadTemplate; context: {section: section}"></ng-container>
</ion-item-divider>
<ion-item class="ion-text-wrap" *ngIf="section.summary">
@ -155,7 +155,7 @@
<!-- Template to render a section download button/progress. -->
<ng-template #sectionDownloadTemplate let-section="section">
<div *ngIf="section && downloadEnabled" class="core-button-spinner ion-float-end">
<div *ngIf="section && downloadEnabled" slot="end">
<!-- Download progress. -->
<ion-badge class="core-course-download-section-progress"
*ngIf="section.isDownloading && section.total > 0 && section.count < section.total">

View File

@ -45,6 +45,13 @@
}
}
.core-button-selector-row {
display: flex;
core-combobox {
flex-grow: 1;
}
}
// @todo
// .item-divider {
// .label {
@ -70,8 +77,6 @@
// @include padding(null, 0, null, null);
// }
// .core-button-selector-row {
// @include safe-area-padding-start($content-padding !important, $content-padding);
// }
//
}

View File

@ -724,7 +724,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo
await Promise.all(modules.map(async (module) => {
const handler = this.getPrefetchHandlerFor(module);
if (!handler || onlyToDisplay || handler.skipListStatus) {
if (!handler || (onlyToDisplay && handler.skipListStatus)) {
return;
}

View File

@ -1,25 +1,26 @@
<ion-item button class="ion-text-wrap" (click)="action('download')" *ngIf="downloadCourseEnabled">
<ion-item button class="ion-text-wrap" (click)="action('download')" *ngIf="downloadCourseEnabled" detail="false">
<ion-icon *ngIf="!prefetch.loading" [name]="prefetch.icon" slot="start" aria-hidden="true"></ion-icon>
<ion-spinner *ngIf="prefetch.loading" slot="start"></ion-spinner>
<ion-label><h2>{{ prefetch.statusTranslatable | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('delete')" *ngIf="prefetch.status == 'downloaded' || prefetch.status == 'outdated'">
<ion-item button class="ion-text-wrap" (click)="action('delete')" detail="false"
*ngIf="prefetch.status == 'downloaded' || prefetch.status == 'outdated'">
<ion-icon name="fas-trash" slot="start" aria-hidden="true"></ion-icon>
<ion-label><h2>{{ 'addon.storagemanager.deletecourse' | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('hide')" *ngIf="!course.hidden">
<ion-item button class="ion-text-wrap" (click)="action('hide')" *ngIf="!course.hidden" detail="false">
<ion-icon name="fas-eye" slot="start" aria-hidden="true"></ion-icon>
<ion-label><h2>{{ 'core.courses.hidecourse' | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('show')" *ngIf="course.hidden">
<ion-item button class="ion-text-wrap" (click)="action('show')" *ngIf="course.hidden" detail="false">
<ion-icon name="fas-eye-slash" slot="start" aria-hidden="true"></ion-icon>
<ion-label><h2>{{ 'core.courses.show' | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('favourite')" *ngIf="!course.isfavourite">
<ion-item button class="ion-text-wrap" (click)="action('favourite')" *ngIf="!course.isfavourite" detail="false">
<ion-icon name="fas-star" slot="start" aria-hidden="true"></ion-icon>
<ion-label><h2>{{ 'core.courses.addtofavourites' | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('unfavourite')" *ngIf="course.isfavourite">
<ion-item button class="ion-text-wrap" (click)="action('unfavourite')" *ngIf="course.isfavourite" detail="false">
<ion-icon name="far-star" slot="start" aria-hidden="true"></ion-icon>
<ion-label><h2>{{ 'core.courses.removefromfavourites' | translate }}</h2></ion-label>
</ion-item>

View File

@ -5,7 +5,7 @@
</div>
<ion-item button lines="none" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
class="core-course-header" [class.item-disabled]="course.visible == 0"
[class.core-course-more-than-title]="course.progress! >= 0">
[class.core-course-more-than-title]="course.progress! >= 0" detail="false">
<ion-label
class="ion-text-wrap core-course-title"
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"

View File

@ -135,7 +135,6 @@
--core-tab-border-color-active: #{$core-tab-border-color-active};
core-tabs, core-tabs-outlet {
--background: var(--core-tabs-background);
ion-slide {
--background: var(--core-tab-background);
--color: var(--core-tab-color);