Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/lint-frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Lint & Build Frontend (Vue)

on:
workflow_call:

jobs:
lint-and-build:
name: Lint & Build
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: ./frontend
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('frontend/package-lock.json') }}
restore-keys: npm-${{ runner.os }}-

- name: Install dependencies
run: npm install

- name: Check formatting (Prettier)
run: npx prettier --check src/

- name: Lint (ESLint)
run: npx eslint src/ --ext .vue,.js,.jsx,.cjs,.mjs

- name: Build
run: npm run build
69 changes: 69 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: CI

on:
pull_request:
branches: [master]
types: [opened, synchronize, reopened]
push:
branches: [master]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
frontend: ${{ steps.filter.outputs.frontend }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
backend:
- 'montage/**'
- 'requirements.txt'
- 'requirements.in'
- 'setup.py'
- 'dockerfile'
frontend:
- 'frontend/**'

test-backend:
name: Test Backend (Python)
needs: changes
if: needs.changes.outputs.backend == 'true'
uses: ./.github/workflows/test-backend.yml

lint-frontend:
name: Lint & Build Frontend (Vue)
needs: changes
if: needs.changes.outputs.frontend == 'true'
uses: ./.github/workflows/lint-frontend.yml

ci-complete:
name: CI Complete
runs-on: ubuntu-latest
needs: [test-backend, lint-frontend]
if: always()
steps:
- name: Check job results
run: |
for job in test-backend lint-frontend; do
case "$job" in
test-backend) result="${{ needs.test-backend.result }}" ;;
lint-frontend) result="${{ needs.lint-frontend.result }}" ;;
esac
if [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
echo "::error::Job $job failed with result: $result"
exit 1
fi
done
echo "All CI jobs passed or were correctly skipped."
33 changes: 33 additions & 0 deletions .github/workflows/test-backend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Test Backend (Python)

on:
workflow_call:

jobs:
test:
name: Run Backend Tests
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Build Docker image
run: docker build -t montage-ci -f dockerfile .

- name: Run pytest
run: |
docker run --rm \
-v "${{ github.workspace }}":/app \
-e PYTHONPATH=/app \
montage-ci \
python -m pytest montage/tests/test_web_basic.py \
-v --tb=short -p no:cacheprovider

- name: Verify backend imports
run: |
docker run --rm \
-v "${{ github.workspace }}":/app \
-e PYTHONPATH=/app \
montage-ci \
python -c "from montage import loaders, rdb, admin_endpoints, juror_endpoints; print('All modules import OK')"
27 changes: 0 additions & 27 deletions .travis.yml

This file was deleted.

1 change: 1 addition & 0 deletions dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ COPY requirements.txt .

RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN pip install pytest

EXPOSE 5000
4 changes: 3 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"preview": "vite preview",
"toolforge:build": "export SHELL=/bin/sh && npm run build && cp -r dist/* ../montage/static",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
"format": "prettier --write src/",
"lint:check": "eslint src/ --ext .vue,.js,.jsx,.cjs,.mjs",
"format:check": "prettier --check src/"
},
"dependencies": {
"@wikimedia/codex": "^1.14.0",
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
<template>
<app-header />
<main class="main-container" >
<main class="main-container">
<router-view />
</main>
<app-footer />
<app-footer />
</template>

<script setup>
import { RouterView } from 'vue-router'
import AppHeader from '@/components/AppHeader.vue'
import AppFooter from '@/components/AppFooter.vue'

</script>

<style scoped>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/assets/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@

.cdx-select-vue__handle {
min-width: 120px;
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{{ $t('montage-about') }}</a
>
<a href="https://github.com/hatnote/montage" class="footer-link" target="_blank">
{{ $t('montage-source-code') }}
{{ $t('montage-source-code') }}
</a>
</div>
<div class="footer-right">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<span>{{ userStore.user.username }}</span>
</div>
<cdx-button action="destructive" weight="quiet" @click="userStore.logout">
{{ $t('montage-login-logout') }}
{{ $t('montage-login-logout') }}
</cdx-button>
</div>
<cdx-select
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Campaign/ActiveCampaign.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ onMounted(() => {
})
})
.catch((error) => {
if (error.response && error.response.status === 403) return;
if (error.response && error.response.status === 403) return
alertService.error(error)
})

Expand Down
19 changes: 9 additions & 10 deletions frontend/src/components/Campaign/AllCampaign.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,22 @@
</div>
</section>
</div>
<clip-loader v-else size="80px" style="padding-top: 120px;" />
<clip-loader v-else size="80px" style="padding-top: 120px" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import _ from 'lodash';
import _ from 'lodash'

import adminService from '@/services/adminService'
import jurorService from '@/services/jurorService'
import alertService from '@/services/alertService';
import alertService from '@/services/alertService'

// Components
import { RouterLink } from 'vue-router'
import CoordinatorCampaignCard from '@/components/Campaign/CoordinatorCampaignCard.vue'
import JurorCampaignCard from '@/components/Campaign/JurorCampaignCard.vue'


// State
const isLoading = ref(false)
const coordinatorCampaigns = ref([])
Expand All @@ -54,7 +53,7 @@ onMounted(() => {
isLoading.value = true

// Fetch all campaigns
const fetchCoordinatorCampaigns = adminService
const fetchCoordinatorCampaigns = adminService
.allCampaigns()
.then((response) => {
coordinatorCampaigns.value = response.data
Expand All @@ -71,7 +70,7 @@ onMounted(() => {
})
})
.catch((error) => {
if (error.response && error.response.status === 403) return;
if (error.response && error.response.status === 403) return
alertService.error(error)
})

Expand All @@ -80,14 +79,14 @@ onMounted(() => {
.allCampaigns()
.then((response) => {
if (!response.data.length) {
jurorCampaigns.value = [];
return;
jurorCampaigns.value = []
return
}

const roundsGroupedByCampaigns = _.groupBy(
response.data.filter((round) => round.status !== 'cancelled'),
'campaign.id'
);
)

let campaignsJuror = _.values(roundsGroupedByCampaigns)

Expand All @@ -112,7 +111,7 @@ onMounted(() => {
})
.catch(alertService.error)

Promise.all([fetchCoordinatorCampaigns, fetchJurorCampaigns]).finally(() => {
Promise.all([fetchCoordinatorCampaigns, fetchJurorCampaigns]).finally(() => {
isLoading.value = false
})
})
Expand Down
27 changes: 21 additions & 6 deletions frontend/src/components/Campaign/JurorCampaignCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,27 @@
</template>
<div v-for="(round, index) in campaign" :key="index" class="juror-campaign-round-card">
<div class="round-header">
<thumbs-up-down v-if="round.vote_method === 'yesno'" class="juror-campaign-round-icon" :size="36" fillColor="white" />
<star-outline v-if="round.vote_method === 'rating'" class="juror-campaign-round-icon" :size="36" fillColor="white" />
<sort v-if="round.vote_method === 'ranking'" class="juror-campaign-round-icon" :size="36" fillColor="white" />
<thumbs-up-down
v-if="round.vote_method === 'yesno'"
class="juror-campaign-round-icon"
:size="36"
fillColor="white"
/>
<star-outline
v-if="round.vote_method === 'rating'"
class="juror-campaign-round-icon"
:size="36"
fillColor="white"
/>
<sort
v-if="round.vote_method === 'ranking'"
class="juror-campaign-round-icon"
:size="36"
fillColor="white"
/>
<div class="round-info">
<p :class="{ 'strikethrough': round.status === 'cancelled' }">{{ round.name }}</p>
<p>({{ $t( getVotingName(round.vote_method) )}} · {{ round.status }})</p>
<p :class="{ strikethrough: round.status === 'cancelled' }">{{ round.name }}</p>
<p>({{ $t(getVotingName(round.vote_method)) }} · {{ round.status }})</p>
</div>
</div>
<div class="card-container">
Expand All @@ -31,7 +46,7 @@
<strong>{{ $t('montage-your-progress') }}:</strong>
{{ (100 - round.percent_tasks_open).toFixed(1) }}% ({{
$t('montage-progress-status', [
(round.total_tasks - round.total_open_tasks) ?? 0,
round.total_tasks - round.total_open_tasks ?? 0,
round.total_tasks ?? 0
])
}})
Expand Down
Loading