diff --git a/.github/workflows/add_contributor.yml b/.github/workflows/add_contributor.yml index 7776f3117e0..4849ca24e34 100644 --- a/.github/workflows/add_contributor.yml +++ b/.github/workflows/add_contributor.yml @@ -1,50 +1,56 @@ -name: Add Contributor to AUTHORS.md +name: Add new contributor to AUTHORS.md on: pull_request: - types: - - opened - - synchronize + types: [opened] jobs: - add_contributor: + check_contributor_exists: runs-on: ubuntu-latest + outputs: + is_contributor_in_file: ${{ steps.check_contributor_step.outputs.exists }} + steps: - name: Checkout repository uses: actions/checkout@v4 + with: + sparse-checkout: . - name: Check if contributor already exists - id: check_contributor + id: check_contributor_step run: | - exists=$(grep -c -F "$GITHUB_ACTOR" AUTHORS.md || true) + exists=$(grep -c -F "${{ github.event.pull_request.user.login }}" AUTHORS.md || true) if [[ $exists -gt 0 ]]; then - echo "exists=true" >> $GITHUB_OUTPUT + echo "exists=true" >> "$GITHUB_OUTPUT" else - echo "exists=false" >> $GITHUB_OUTPUT + echo "exists=false" >> "$GITHUB_OUTPUT" fi - - name: Get contributor's full name - id: get_full_name - if: steps.check_contributor.outputs.exists == 'false' + add_contributor: + runs-on: ubuntu-latest + needs: check_contributor_exists + + if: needs.check_contributor_exists.outputs.is_contributor_in_file == 'false' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + + - name: Get contributor's full name and append to AUTHORS.md file run: | - username=$GITHUB_ACTOR - access_token=$GITHUB_TOKEN - full_name=$(curl -s -H "Authorization: token $access_token" "https://api.github.com/users/$username" | jq -r '.name') + username=${{ github.event.pull_request.user.login }} + full_name=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/users/$username" | jq -r '.name') if [[ "$full_name" == "" || "$full_name" == "null" ]]; then full_name='-' fi - echo "full_name=$full_name" >> $GITHUB_OUTPUT + echo "| $full_name | $username |" >> AUTHORS.md - - name: Append contributor to AUTHORS.md - id: append_contributor - if: steps.check_contributor.outputs.exists == 'false' + - name: Commit and push changes to the contributor's PR branch run: | - full_name=${{ steps.get_full_name.outputs.full_name }} - echo "| $full_name | $GITHUB_ACTOR |" >> AUTHORS.md - - - name: Commit and push changes to branch - id: commit_changes - if: steps.check_contributor.outputs.exists == 'false' - uses: pre-commit-ci/lite-action@v1.0.1 - with: - msg: Add ${{ env.GITHUB_ACTOR }} to AUTHORS.md + git config --global user.name 'github-actions[bot]' + git config --global user.email 'github-actions[bot]@users.noreply.github.com' + git add AUTHORS.md + git commit -m "Add ${{ github.event.pull_request.user.login }} to AUTHORS.md" + git push origin ${{ github.head_ref }} diff --git a/.github/workflows/build_whl.yml b/.github/workflows/build_whl.yml index c8182263389..a692b37913c 100644 --- a/.github/workflows/build_whl.yml +++ b/.github/workflows/build_whl.yml @@ -35,7 +35,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '16.x' + node-version: '18.x' - name: Install Yarn run: npm install -g yarn - name: Get yarn cache directory path diff --git a/.github/workflows/check_licenses.yml b/.github/workflows/check_licenses.yml index 7f369f75e88..54c0dde3bdb 100644 --- a/.github/workflows/check_licenses.yml +++ b/.github/workflows/check_licenses.yml @@ -33,7 +33,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '16.x' + node-version: '18.x' - name: Cache Node.js modules uses: actions/cache@v3 with: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index f40296f5d3a..e8d87375d1f 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -36,7 +36,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '16.x' + node-version: '18.x' - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT diff --git a/.github/workflows/yarn.yml b/.github/workflows/yarn.yml index 20123f3823c..3041860e73b 100644 --- a/.github/workflows/yarn.yml +++ b/.github/workflows/yarn.yml @@ -33,7 +33,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v4 with: - node-version: '16.x' + node-version: '18.x' - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT diff --git a/AUTHORS.md b/AUTHORS.md index 36686477121..b7383333720 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -82,7 +82,6 @@ If you have contributed to Kolibri, feel free to add your name and Github accoun | Shanavas M | shanavas786 | | - | shivangtripathi | | Udith Prabhu | udithprabhu | -| Vivek Agrawal | vkWeb | | Whitney Zhu | whitzhu | | Carol Willing | willingc | | Yash Jipkate | YashJipkate | diff --git a/docker/base.dockerfile b/docker/base.dockerfile index 61a2ca8ce89..09ed0080274 100644 --- a/docker/base.dockerfile +++ b/docker/base.dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:jammy -ENV NODE_VERSION=16.20.0 +ENV NODE_VERSION=18.19.0 # install required packages RUN apt-get update && \ @@ -22,7 +22,7 @@ RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources # install nodejs and yarn RUN apt-get update && \ ARCH=$(dpkg --print-architecture) && \ - curl -sSO https://deb.nodesource.com/node_16.x/pool/main/n/nodejs/nodejs_$NODE_VERSION-1nodesource1_$ARCH.deb && \ + curl -sSO https://deb.nodesource.com/node_18.x/pool/main/n/nodejs/nodejs_$NODE_VERSION-1nodesource1_$ARCH.deb && \ dpkg -i ./nodejs_$NODE_VERSION-1nodesource1_$ARCH.deb && \ rm nodejs_$NODE_VERSION-1nodesource1_$ARCH.deb && \ apt-get install yarn diff --git a/docker/build_whl.dockerfile b/docker/build_whl.dockerfile index deb7096324b..744959b06b8 100644 --- a/docker/build_whl.dockerfile +++ b/docker/build_whl.dockerfile @@ -1,6 +1,6 @@ FROM ubuntu:bionic -ENV NODE_VERSION=16.20.0 +ENV NODE_VERSION=18.19.0 # install required packages RUN apt-get update && \ @@ -24,7 +24,7 @@ RUN (curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -) && \ # install nodejs and yarn RUN apt-get update && \ - curl -sSO https://deb.nodesource.com/node_16.x/pool/main/n/nodejs/nodejs_$NODE_VERSION-1nodesource1_amd64.deb && \ + curl -sSO https://deb.nodesource.com/node_18.x/pool/main/n/nodejs/nodejs_$NODE_VERSION-1nodesource1_amd64.deb && \ dpkg -i ./nodejs_$NODE_VERSION-1nodesource1_amd64.deb && \ rm nodejs_$NODE_VERSION-1nodesource1_amd64.deb && \ apt-get install yarn diff --git a/docs/getting_started.rst b/docs/getting_started.rst index f464bd42d0c..5d7dc833203 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -156,7 +156,7 @@ Note that the ``--upgrade`` flags above can usually be omitted to speed up the p Install Node.js, Yarn and other dependencies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -#. Install `Node.js `__ (version 16.x is required) +#. Install `Node.js `__ (version 18.x is required) #. Install `Yarn `__ #. Install non-python project-specific dependencies @@ -170,7 +170,7 @@ The Python project-specific dependencies installed above will install ``nodeenv` # If you are setting up the release-v0.15.x branch or earlier: nodeenv -p --node=10.17.0 # If you are setting up the develop branch: - nodeenv -p --node=16.20.0 + nodeenv -p --node=18.19.0 npm install -g yarn # other required project dependencies diff --git a/docs/howtos/nodeenv.md b/docs/howtos/nodeenv.md index 3b2edbbf21f..6b2f7c5f982 100644 --- a/docs/howtos/nodeenv.md +++ b/docs/howtos/nodeenv.md @@ -18,14 +18,14 @@ $ nodeenv -l but this lists out everything. Alternatively, here's a one line bash function that can be used to determine that version: ```bash $ function latest-node() { curl -s "https://nodejs.org/dist/latest-v$1.x/" | egrep -m 1 -o "$1\.[0-9]+\.[0-9]+" | head -1; } -$ latest-node 16 -16.16.0 +$ latest-node 18 +18.19.0 ``` Once you've determined the version, you can install it: ```bash -$ nodeenv --python-virtualenv --node 16.16.0 - * Install prebuilt node (16.16.0) ..... done. +$ nodeenv --python-virtualenv --node 18.19.0 + * Install prebuilt node (18.19.0) ..... done. * Appending data to /home/bjester/Projects/learningequality/kolibri/venv/bin/activate * Appending data to /home/bjester/Projects/learningequality/kolibri/venv/bin/activate.fish ``` diff --git a/kolibri/core/assets/src/views/BottomAppBar.vue b/kolibri/core/assets/src/views/BottomAppBar.vue index 46e61464477..5b6148d3192 100644 --- a/kolibri/core/assets/src/views/BottomAppBar.vue +++ b/kolibri/core/assets/src/views/BottomAppBar.vue @@ -47,7 +47,6 @@ } .bottom-sm { - height: auto; min-height: 72px; } diff --git a/kolibri/core/assets/src/views/CorePage/AppBarPage.vue b/kolibri/core/assets/src/views/CorePage/AppBarPage.vue index bf1e9e53d98..479c6f797d4 100644 --- a/kolibri/core/assets/src/views/CorePage/AppBarPage.vue +++ b/kolibri/core/assets/src/views/CorePage/AppBarPage.vue @@ -51,8 +51,6 @@ @cancel="languageModalShown = false" /> - - @@ -69,7 +67,6 @@ import { LearnerDeviceStatus } from 'kolibri.coreVue.vuex.constants'; import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; import { isTouchDevice } from 'kolibri.utils.browserInfo'; - import MeteredConnectionNotificationModal from 'kolibri-common/components/MeteredConnectionNotificationModal'; import AppBar from '../AppBar'; import StorageNotification from '../StorageNotification'; import useUserSyncStatus from '../../composables/useUserSyncStatus'; @@ -78,7 +75,6 @@ name: 'AppBarPage', components: { AppBar, - MeteredConnectionNotificationModal, LanguageSwitcherModal, ScrollingHeader, SideNav, diff --git a/kolibri/core/assets/src/views/userAccounts/UsernameTextbox.vue b/kolibri/core/assets/src/views/userAccounts/UsernameTextbox.vue index 522e9c0bb1b..6d1ff15cf79 100644 --- a/kolibri/core/assets/src/views/userAccounts/UsernameTextbox.vue +++ b/kolibri/core/assets/src/views/userAccounts/UsernameTextbox.vue @@ -9,6 +9,7 @@ :maxlength="30" :invalid="Boolean(shownInvalidText)" :invalidText="shownInvalidText" + autocomplete="username" @blur="blurred = true" @input="handleInput" /> diff --git a/kolibri/plugins/device/assets/src/views/AvailableChannelsPage/index.vue b/kolibri/plugins/device/assets/src/views/AvailableChannelsPage/index.vue index 8dcf45af1b0..aa933f05f30 100644 --- a/kolibri/plugins/device/assets/src/views/AvailableChannelsPage/index.vue +++ b/kolibri/plugins/device/assets/src/views/AvailableChannelsPage/index.vue @@ -331,9 +331,9 @@ return this.$router.push({ query: newQuery }); }, handleSubmitToken({ token, channels }) { + this.showTokenModal = false; if (channels.length > 1) { if (this.$route.query.token !== token) { - this.disableModal = true; this.$router.push({ ...this.$route, query: { @@ -341,8 +341,6 @@ token, }, }); - } else { - this.showTokenModal = false; } } else { this.goToSelectContentPageForChannel(channels[0]); diff --git a/kolibri/plugins/learn/assets/src/composables/useDeviceSettings.js b/kolibri/plugins/learn/assets/src/composables/useDeviceSettings.js index f8ad92de24e..03a0dc22703 100644 --- a/kolibri/plugins/learn/assets/src/composables/useDeviceSettings.js +++ b/kolibri/plugins/learn/assets/src/composables/useDeviceSettings.js @@ -1,5 +1,8 @@ -import { computed } from 'kolibri.lib.vueCompositionApi'; +import { computed, ref } from 'kolibri.lib.vueCompositionApi'; import store from 'kolibri.coreVue.vuex.store'; +import plugin_data from 'plugin_data'; + +const allowDownloadOnMeteredConnection = ref(plugin_data.allowDownloadOnMeteredConnection); export default function useDeviceSettings() { const allowGuestAccess = computed(() => store.getters.allowGuestAccess); @@ -8,5 +11,6 @@ export default function useDeviceSettings() { return { allowGuestAccess, canAccessUnassignedContent, + allowDownloadOnMeteredConnection, }; } diff --git a/kolibri/plugins/learn/assets/src/views/ExploreLibrariesPage/index.vue b/kolibri/plugins/learn/assets/src/views/ExploreLibrariesPage/index.vue index 8ff167cabc1..5bb8facf722 100644 --- a/kolibri/plugins/learn/assets/src/views/ExploreLibrariesPage/index.vue +++ b/kolibri/plugins/learn/assets/src/views/ExploreLibrariesPage/index.vue @@ -173,7 +173,7 @@ }, showingLibraries: { message: 'Showing libraries on other devices around you', - continue: 'Description of the kind of devices displayed', + context: 'Description of the kind of devices displayed', }, // The strings below are not used currently used in the code. // This is to aid the translation of the string diff --git a/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue b/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue index 95642ed9d15..10583f73656 100644 --- a/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue +++ b/kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue @@ -10,6 +10,10 @@ isOnMyOwnUser @cancel="hideWelcomeModal" /> + @@ -166,12 +170,15 @@ import samePageCheckGenerator from 'kolibri.utils.samePageCheckGenerator'; import { ContentNodeResource } from 'kolibri.resources'; import { mapState, mapGetters } from 'vuex'; + import MeteredConnectionNotificationModal from 'kolibri-common/components/MeteredConnectionNotificationModal.vue'; + import appCapabilities, { checkCapability } from 'kolibri.utils.appCapabilities'; import SidePanelModal from '../SidePanelModal'; import SearchFiltersPanel from '../SearchFiltersPanel'; import { KolibriStudioId, PageNames } from '../../constants'; import useCardViewStyle from '../../composables/useCardViewStyle'; import useContentLink from '../../composables/useContentLink'; import useCoreLearn from '../../composables/useCoreLearn'; + import useDeviceSettings from '../../composables/useDeviceSettings'; import { currentDeviceData, setCurrentDevice, @@ -204,6 +211,7 @@ ChannelCardGroupGrid, SidePanelModal, LearningActivityChip, + MeteredConnectionNotificationModal, ResumableContentGrid, SearchResultsGrid, SearchFiltersPanel, @@ -218,6 +226,7 @@ const router = currentInstance.$router; const { isUserLoggedIn, isCoach, isAdmin, isSuperuser } = useUser(); + const { allowDownloadOnMeteredConnection } = useDeviceSettings(); const { searchTerms, displayingSearchResults, @@ -361,6 +370,7 @@ showLibrary(); return { + allowDownloadOnMeteredConnection, canAddDownloads, canDownloadExternally, displayingSearchResults, @@ -402,6 +412,7 @@ isLocalLibraryEmpty: false, metadataSidePanelContent: null, mobileSidePanelIsOpen: false, + usingMeteredConnection: true, }; }, computed: { @@ -421,6 +432,19 @@ window.localStorage.getItem(welcomeDismissalKey) !== 'true' ); }, + showOtherLibraries() { + const validUser = !this.deviceId && this.isUserLoggedIn; + if (!validUser) { + return false; + } + if (!checkCapability('check_is_metered')) { + return true; + } + if (this.allowDownloadOnMeteredConnection) { + return true; + } + return !this.usingMeteredConnection; + }, channelsLabel() { if (this.deviceId) { if (this.deviceId === this.studioId) { @@ -481,6 +505,18 @@ if (window.sessionStorage.getItem(welcomeDismissalKey) !== 'true') { this.$store.commit('SET_WELCOME_MODAL_VISIBLE', true); } + + // parallels logic for showOtherLibraries + if ( + !this.deviceId && + this.isUserLoggedIn && + !this.allowDownloadOnMeteredConnection && + checkCapability('check_is_metered') + ) { + appCapabilities.checkIsMetered().then(isMetered => { + this.usingMeteredConnection = isMetered; + }); + } }, methods: { hideWelcomeModal() { diff --git a/kolibri/plugins/learn/kolibri_plugin.py b/kolibri/plugins/learn/kolibri_plugin.py index 6a6e2fc688d..221793b430a 100644 --- a/kolibri/plugins/learn/kolibri_plugin.py +++ b/kolibri/plugins/learn/kolibri_plugin.py @@ -64,6 +64,9 @@ def plugin_data(self): from kolibri.core.discovery.well_known import CENTRAL_CONTENT_BASE_INSTANCE_ID return { + "allowDownloadOnMeteredConnection": get_device_setting( + "allow_download_on_metered_connection" + ), "allowGuestAccess": get_device_setting("allow_guest_access"), "allowLearnerDownloads": get_device_setting( "allow_learner_download_resources" diff --git a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SettingUpKolibri.vue b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SettingUpKolibri.vue index e26eca6e8e2..344b96f407c 100644 --- a/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SettingUpKolibri.vue +++ b/kolibri/plugins/setup_wizard/assets/src/views/onboarding-forms/SettingUpKolibri.vue @@ -1,21 +1,23 @@