Skip to content

Commit

Permalink
Merge pull request #649 from corypride/clarity-in-knowledge-center-613
Browse files Browse the repository at this point in the history
Sorting options and clarity in the Knowledge Center
  • Loading branch information
carddev81 authored Jan 14, 2025
2 parents 0a8c319 + 7b98296 commit dae0366
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 99 deletions.
16 changes: 5 additions & 11 deletions backend/src/database/helpful_links.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package database
import (
"UnlockEdv2/src/models"
"fmt"
"strings"
)

type HelpfulLinkResp struct {
Expand All @@ -19,13 +20,6 @@ func (db *DB) GetHelpfulLinks(page, perPage int, search, orderBy string, onlyVis
tx := db.Model(&models.HelpfulLink{}).Select("helpful_links.*, EXISTS(?) as is_favorited", subQuery)
var total int64

validOrder := map[string]bool{
"title ASC": true,
"title DESC": true,
"created_at ASC": true,
"created_at DESC": true,
}

if onlyVisible {
tx = tx.Where("visibility_status = ?", true)
}
Expand All @@ -34,11 +28,11 @@ func (db *DB) GetHelpfulLinks(page, perPage int, search, orderBy string, onlyVis
search = "%" + search + "%"
tx = tx.Where("LOWER(title) LIKE ?", search)
}

if valid, ok := validOrder[orderBy]; ok && valid {
switch strings.ToLower(orderBy) {
case "most_popular":
tx = tx.Order("COUNT(f.id) DESC")
default:
tx = tx.Order(orderBy)
} else {
tx = tx.Order("created_at DESC")
}

if err := tx.Count(&total).Error; err != nil {
Expand Down
20 changes: 1 addition & 19 deletions backend/src/database/libraries.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (db *DB) GetAllLibraries(page, perPage, days int, userId, facilityId uint,
}

switch strings.ToLower(orderBy) {
case "most_favorited":
case "most_popular":
tx = tx.Select(`
libraries.*,
COUNT(f.id) AS favorite_count,
Expand All @@ -82,24 +82,6 @@ func (db *DB) GetAllLibraries(page, perPage, days int, userId, facilityId uint,
}
tx = tx.Group("libraries.id").Order("favorite_count DESC")

case "least_favorited":
tx = tx.Select(`
libraries.*,
COUNT(f.id) AS favorite_count,
EXISTS (
SELECT 1
FROM open_content_favorites f
WHERE f.content_id = libraries.id
AND f.open_content_provider_id = libraries.open_content_provider_id
AND f.user_id = ?
) AS is_favorited`, userId)
if !isFeatured {
tx = tx.Joins(`LEFT JOIN open_content_favorites f
ON f.content_id = libraries.id
AND f.open_content_provider_id = libraries.open_content_provider_id`)
}
tx = tx.Group("libraries.id").
Order("favorite_count ASC")
default:
tx = tx.Order(orderBy)
}
Expand Down
24 changes: 8 additions & 16 deletions backend/src/database/videos.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package database

import (
"UnlockEdv2/src/models"
"strings"
)

func (db *DB) GetVideoByID(id int) (*models.Video, error) {
Expand Down Expand Up @@ -70,29 +71,20 @@ func (db *DB) GetAllVideos(onlyVisible bool, page, perPage int, search, orderBy
AND f.user_id = ?
) AS is_favorited`, userID)
var total int64
validOrder := map[string]bool{
"title ASC": true,
"title DESC": true,
"created_at ASC": true,
"created_at DESC": true,
"favorited": true,
}

if onlyVisible {
tx = tx.Where("visibility_status = ?", true)
}
if search != "" {
search = "%" + search + "%"
tx = tx.Where("LOWER(title) LIKE ? OR LOWER(channel_title) LIKE ?", search, search)
}
if valid, ok := validOrder[orderBy]; ok && valid {
if orderBy == "favorited" {
tx = tx.Joins("LEFT JOIN open_content_favorites f ON f.content_id = videos.id AND f.open_content_provider_id = videos.open_content_provider_id").
Group("videos.id").Order("COUNT(f.id) DESC")
} else {
tx = tx.Order(orderBy)
}
} else {
tx = tx.Order("created_at DESC")
switch strings.ToLower(orderBy) {
case "most_popular":
tx = tx.Joins("LEFT JOIN open_content_favorites f ON f.content_id = videos.id AND f.open_content_provider_id = videos.open_content_provider_id").
Group("videos.id").Order("COUNT(f.id) DESC")
default:
tx = tx.Order(orderBy)
}
if err := tx.Count(&total).Error; err != nil {
return 0, nil, newGetRecordsDBError(err, "videos")
Expand Down
3 changes: 2 additions & 1 deletion backend/src/handlers/helpful_links_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ func (srv *Server) changeSortOrder(w http.ResponseWriter, r *http.Request, log s

func (srv *Server) handleGetHelpfulLinks(w http.ResponseWriter, r *http.Request, log sLog) error {
search := r.URL.Query().Get("search")
orderBy := r.URL.Query().Get("order_by")
onlyVisible := r.URL.Query().Get("visibility") == "true"
if !userIsAdmin(r) {
onlyVisible = true
}
userID := srv.getUserID(r)
page, perPage := srv.getPaginationInfo(r)
total, links, err := srv.Db.GetHelpfulLinks(page, perPage, search, HelpfulSortOrder[srv.getFacilityID(r)], onlyVisible, userID)
total, links, err := srv.Db.GetHelpfulLinks(page, perPage, search, orderBy, onlyVisible, userID)
if err != nil {
return newInternalServerServiceError(err, "error fetching helpful links")
}
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/Components/LibraryLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
Library,
ServerResponseMany,
UserRole,
FilterLibrariesAdmin
FilterLibrariesVidsandHelpfulLinksAdmin
} from '@/common';
import DropdownControl from '@/Components/inputs/DropdownControl';
import SearchBar from '@/Components/inputs/SearchBar';
Expand Down Expand Up @@ -32,7 +32,9 @@ export default function LibaryLayout({
const [filterLibrariesAdmin, setFilterLibrariesAdmin] = useState<string>(
LibraryAdminVisibility['All Libraries']
);
const [orderBy, setOrderBy] = useState<string>(FilterLibrariesAdmin.Newest);
const [orderBy, setOrderBy] = useState<string>(
FilterLibrariesVidsandHelpfulLinksAdmin['Title (A to Z)']
);
let role = user.role;
if (studentView) {
role = UserRole.Student;
Expand Down Expand Up @@ -104,7 +106,7 @@ export default function LibaryLayout({
/>
<DropdownControl
label="Filter by"
enumType={FilterLibrariesAdmin}
enumType={FilterLibrariesVidsandHelpfulLinksAdmin}
setState={setOrderBy}
/>
</>
Expand Down
47 changes: 11 additions & 36 deletions frontend/src/Pages/HelpfulLinksManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
HelpfulLink,
FilterLibrariesVidsandHelpfulLinksAdmin,
ModalType,
ServerResponseOne,
ToastState,
Expand All @@ -20,8 +21,8 @@ import { useDebounceValue } from 'usehooks-ts';
import useSWR from 'swr';
import { AxiosError } from 'axios';
import API from '@/api/api';
import SortByPills from '@/Components/pill-labels/SortByPills';
import { isAdministrator, useAuth } from '@/useAuth';
import DropdownControl from '@/Components/inputs/DropdownControl';

export default function HelpfulLinksManagement() {
const { user } = useAuth();
Expand All @@ -33,17 +34,19 @@ export default function HelpfulLinksManagement() {
const [pageQuery, setPageQuery] = useState<number>(1);
const [searchTerm, setSearchTerm] = useState<string>('');
const searchQuery = useDebounceValue(searchTerm, 500);
const [sortQuery, setSortQuery] = useState<string>(
FilterLibrariesVidsandHelpfulLinksAdmin['Title (A to Z)']
);
const { toaster } = useToast();

const { data, mutate, error, isLoading } = useSWR<
ServerResponseOne<HelpfulLinkAndSort>,
AxiosError
>(
`/api/helpful-links?search=${searchQuery[0]}&page=${pageQuery}&per_page=${perPage}`
`/api/helpful-links?search=${searchQuery[0]}&page=${pageQuery}&per_page=${perPage}&order_by=${sortQuery}`
);
const helpfulLinks = data?.data.helpful_links ?? [];
const meta = data?.data.meta;
let globalSortOrder = data?.data.sort_order;

function updateLinks() {
addLinkModal.current?.close();
Expand Down Expand Up @@ -87,28 +90,6 @@ export default function HelpfulLinksManagement() {
void mutate();
};

async function updateGlobalSort(sort: string) {
const response = await API.put<
{ message: string },
{ sort_order: string }
>('helpful-links/sort', { sort_order: sort });
if (response.success) {
globalSortOrder = sort;
void mutate();
}
toaster(
response.message,
response.success ? ToastState.success : ToastState.error
);
}

const sortPills = [
{ name: 'Date Added ↓', value: 'created_at DESC' },
{ name: 'Date Added ↑', value: 'created_at ASC' },
{ name: 'Title (A-Z)', value: 'title ASC' },
{ name: 'Title (Z-A)', value: 'title DESC' }
];

return (
<>
<div className="flex flex-row justify-between">
Expand All @@ -118,17 +99,11 @@ export default function HelpfulLinksManagement() {
searchTerm={searchTerm}
changeCallback={handleChange}
/>
<h3 className="ml-2">Order:</h3>
{sortPills.map((label) => (
<SortByPills
key={label.value + label.name}
label={label}
updateSort={() =>
void updateGlobalSort(label.value)
}
isSelected={label.value === globalSortOrder}
/>
))}
<DropdownControl
label="Order by"
setState={setSortQuery}
enumType={FilterLibrariesVidsandHelpfulLinksAdmin}
/>
</div>
{/* add links button */}
<div
Expand Down
14 changes: 6 additions & 8 deletions frontend/src/Pages/VideoManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
ToastState,
Video,
ServerResponseMany,
UserRole
UserRole,
FilterLibrariesVidsandHelpfulLinksAdmin
} from '../common';
import AddVideosForm from '@/Components/forms/AddVideosForm';
import Modal from '@/Components/Modal';
Expand Down Expand Up @@ -34,7 +35,9 @@ export default function VideoManagement() {
const [polling, setPolling] = useState<boolean>(false);
const [perPage, setPerPage] = useState(12);
const [pageQuery, setPageQuery] = useState(1);
const [sortQuery, setSortQuery] = useState('created_at DESC');
const [sortQuery, setSortQuery] = useState<string>(
FilterLibrariesVidsandHelpfulLinksAdmin['Title (A to Z)']
);
const navigate = useNavigate();
const { toaster } = useToast();
const { data, mutate, error, isLoading } = useSWR<
Expand Down Expand Up @@ -108,12 +111,7 @@ export default function VideoManagement() {
<DropdownControl
label="Order by"
setState={setSortQuery}
enumType={{
'Date Added ↓': 'created_at DESC',
'Date Added ↑': 'created_at ASC',
'Title (A-Z)': 'title ASC',
'Title (Z-A)': 'title DESC'
}}
enumType={FilterLibrariesVidsandHelpfulLinksAdmin}
/>
</div>
<button
Expand Down
12 changes: 7 additions & 5 deletions frontend/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -826,18 +826,20 @@ export enum FilterLibraries {
'Oldest' = 'created_at ASC',
'Favorited' = 'most_favorited'
}

export enum LibraryAdminVisibility {
'All Libraries' = 'all',
'Visible' = 'visible',
'Hidden' = 'hidden',
'Featured' = 'featured'
}

export enum FilterLibrariesAdmin {
'Most Favorited' = 'most_favorited',
'Least Favorited' = 'least_favorited',
'Newest' = 'created_at DESC',
'Oldest' = 'created_at ASC'
export enum FilterLibrariesVidsandHelpfulLinksAdmin {
'Title (A to Z)' = 'title ASC',
'Title (Z to A)' = 'title DESC',
'Date Added (Newest First)' = 'created_at DESC',
'Date Added (Oldest First)' = 'created_at ASC',
'Most Popular' = 'most_popular'
}

export enum Timezones {
Expand Down

0 comments on commit dae0366

Please sign in to comment.