Skip to content

Commit

Permalink
Implement table.
Browse files Browse the repository at this point in the history
Fixes #16
  • Loading branch information
JoshStrobl committed Aug 23, 2023
1 parent bd4a8f9 commit 84767b0
Show file tree
Hide file tree
Showing 31 changed files with 489 additions and 7 deletions.
13 changes: 13 additions & 0 deletions docs/developer/workflow/third-party-release-schedules.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: This document contains an aggregated list of third-party release schedules relevant to Budgie Desktop development.
keywords:
- third-party
- release schedule
title: Third-party Release Schedules
---

import ThirdPartyReleaseTable from "@site/src/components/schedule/ThirdPartyReleaseTable";

This document contains an aggregated list of third-party release schedules relevant to Budgie Desktop development.

<ThirdPartyReleaseTable />
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mdx-js/react": "^1.6.22",
"@mobily/ts-belt": "^3.13.1",
"@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.5",
"add-to-calendar-button-react": "^2.3.3",
"clsx": "^2.0.0",
"ics": "^3.4.0",
"lodash": "^4.17.21",
"luxon": "^3.4.0",
"prism-react-renderer": "^2.0.6",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"react-icons": "^4.10.1"
},
"devDependencies": {
"@docusaurus/eslint-plugin": "^2.4.1",
Expand Down
2 changes: 1 addition & 1 deletion src/components/getting-budgie/OSCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type OSCardProps = {
export const OSCard = ({ info }: OSCardProps) => {
const aboveSm = useMediaQuery(SiteTheme.breakpoints.up("sm"));
const kebabName = kebabCase(toLower(info.name));
const logo = useBaseUrl(`/img/distribution/logos/${kebabName}.svg`);
const logo = useBaseUrl(`/img/logos/${kebabName}.svg`);
const screenshot = useBaseUrl(`/img/distribution/screenshots/${kebabName}.webp`);

const hasLatestOOTB = info.budgieVersion === LATEST_BUDGIE_RELEASE.version;
Expand Down
2 changes: 1 addition & 1 deletion src/components/getting-budgie/SupportList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const SupportList = () => {
<Stack gap={4} key="SupportList-ManualItems">
{manualItems.map((info) => {
const kebabName = kebabCase(toLower(info.name));
const logo = useBaseUrl(`/img/distribution/logos/${kebabName}.svg`);
const logo = useBaseUrl(`/img/logos/${kebabName}.svg`);

return (
<Box className={`ManualOSCard card`} key={`SupportList-ManualItem-${info.name}-Box`}>
Expand Down
2 changes: 1 addition & 1 deletion src/components/home/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const Header = () => {
</Link>
</Stack>
<Container maxWidth="fullhd">
<Box bgcolor="primary.dark" borderRadius={4} p={2} width={1}>
<Box bgcolor="misc.dark" borderRadius={4} p={2} width={1}>
<Box
borderRadius={2}
position="relative"
Expand Down
34 changes: 34 additions & 0 deletions src/components/schedule/MultiSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Autocomplete, Box, Chip, TextField } from "@mui/material";
import React from "react";

interface MultiSelectProps<T> {
defaultValues: T[];
id: string;
label: string;
onChange: (values: T[]) => void;
options: T[];
}

export const MultiSelect = <T,>({ defaultValues, id, label, onChange, options }: MultiSelectProps<T>) => {
return (
<Autocomplete
defaultValue={defaultValues}
id={id}
multiple
onChange={(_, v) => {
onChange(v);
}}
options={options}
renderInput={(params) => <TextField {...params} variant="standard" label={label} />}
renderTags={(selected, getTagProps) => {
return (
<Box sx={{ paddingBlock: 1 }}>
{selected.map((value, index) => (
<Chip key={value} label={value as string} {...getTagProps({ index })} />
))}
</Box>
);
}}
/>
);
};
246 changes: 246 additions & 0 deletions src/components/schedule/ThirdPartyReleaseTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import {
Avatar,
Box,
Chip,
FormControlLabel,
Stack,
Switch,
TableCell,
TableContainer,
TableHead,
TableRow,
ToggleButton,
Typography,
styled,
useColorScheme,
} from "@mui/material";
import { UnifiedReleaseSchedules } from "@site/src/data/schedules/unified";
import { CalendarEventCategory, CalendarEventStrictType, CalendarEventType } from "@site/src/types";
import React, { useMemo, useState } from "react";

import Link from "@docusaurus/Link";
import Translate, { translate } from "@docusaurus/Translate";
import { A, pipe } from "@mobily/ts-belt";
import { AcUnit, Construction, EventBusy, QuestionMark, RocketLaunch } from "@mui/icons-material";
import BiotechIcon from "@mui/icons-material/Biotech";
import FilterAltIcon from "@mui/icons-material/FilterAlt";
import { AddToCalendarButton } from "add-to-calendar-button-react";
import { DateTime, Interval } from "luxon";
import { TbAlpha, TbBarrierBlock, TbBeta, TbGitBranch, TbGrave } from "react-icons/tb";
import { MultiSelect } from "./MultiSelect";

const CategoryChip = ({ c }: { c: CalendarEventCategory }) => {
const { mode } = useColorScheme();
return (
<Chip
avatar={<Avatar alt={c} src={`/img/logos/${c.toLowerCase()}.svg`} />}
label={c}
sx={{
".MuiChip-avatar": {
filter: c === CalendarEventCategory.GNOME && mode === "dark" ? "invert(1) brightness(1)" : undefined,
},
width: "max-content",
}}
/>
);
};

const EventTypeToIcon = ({ t }: { t: CalendarEventType }) => {
const UseIcon = (() => {
switch (t) {
case CalendarEventType.ABI_FREEZE:
case CalendarEventType.BETA_FREEZE:
case CalendarEventType.BRANCH_FREEZE:
case CalendarEventType.FEATURE_FREEZE:
case CalendarEventType.FINAL_FREEZE:
case CalendarEventType.IMPORT_FREEZE:
return <AcUnit />;
case CalendarEventType.ALPHA:
return <TbAlpha style={{ fontSize: "1.5em" }} />;
case CalendarEventType.BETA_RELEASE:
return <TbBeta style={{ fontSize: "1.5em" }} />;
case CalendarEventType.BRANCHING:
return <TbGitBranch style={{ fontSize: "1.5em" }} />;
case CalendarEventType.CHANGE_CHECKPOINT_SELF_CONTAINED:
case CalendarEventType.CHANGE_CHECKPOINT_TESTABLE:
return <TbBarrierBlock style={{ fontSize: "1.5em" }} />;
case CalendarEventType.CODE_COMPLETE_DEADLINE:
return <EventBusy />;
case CalendarEventType.EOL:
return <TbGrave style={{ fontSize: "1.5em" }} />;
case CalendarEventType.RELEASE:
case CalendarEventType.START:
return <RocketLaunch />;
case CalendarEventType.RELEASE_CANDIDATE:
return <Construction />;
case CalendarEventType.TESTING_WEEK:
return <BiotechIcon />;
default:
return <QuestionMark />;
}
})();

return <Box sx={{ height: "1.5em", minWidth: "2em" }}>{UseIcon}</Box>;
};

const ThirdPartyReleaseTable = () => {
const { mode } = useColorScheme();

const [showFilters, setShowFilters] = useState(false);
const [showPastEvents, setShowPastEvents] = useState(true);
const [selectedCategories, setSelectedCategories] = useState<CalendarEventCategory[]>(
Object.values(CalendarEventCategory)
);
const [selectedTypes, setSelectedTypes] = useState<CalendarEventType[]>(Object.values(CalendarEventType));

const today = useMemo(() => DateTime.now().setZone("utc", { keepLocalTime: true }).startOf("day"), []);

const filteredEvents = useMemo(
() =>
pipe(
UnifiedReleaseSchedules.reduce<CalendarEventStrictType[]>(
(acc, e) => [...acc, ...e.types.map((t) => ({ ...e, type: t }))],
[]
),
A.filter((e) => selectedCategories.includes(e.category)),
A.filter((e) => selectedTypes.includes(e.type)),
A.filter((e) => (showPastEvents ? true : DateTime.fromISO(e.dates[0]).diff(today).milliseconds > 0))
),
[selectedCategories, selectedTypes, showPastEvents, today]
);

const firstUpcomingEvent = filteredEvents.find((e) => {
const startDate = DateTime.fromISO(e.dates[0]);
const endDate = DateTime.fromISO(e.dates[1]).plus({ days: e.dates[0] === e.dates[0] ? 1 : 0 });
const diff = Interval.fromDateTimes(startDate, endDate);

const currentOrUpcoming = diff.contains(today) || startDate.diff(today).milliseconds > 0;
return currentOrUpcoming;
});

return (
<Stack gap={4}>
<Stack direction="row" justifyContent="space-between">
<ToggleButton onChange={() => setShowFilters(!showFilters)} selected={showFilters} value={showFilters}>
<FilterAltIcon />
</ToggleButton>
<AddToCalendarButton
buttonStyle="default"
hideBackground
hideButton={false}
hideBranding={true}
name="Buddies of Budgie: Third-party Project Schedules"
icsFile={`${location.origin}/calendars/third-party-schedules.ics`}
lightMode={mode}
options={["Apple", "Google", "iCal", "Outlook.com", "Yahoo", "Microsoft365", "MicrosoftTeams"]}
subscribe
startDate={UnifiedReleaseSchedules[0].dates[0]}
trigger="click"
></AddToCalendarButton>
</Stack>
{showFilters && (
<>
<FormControlLabel
control={<Switch color="success" defaultChecked onChange={() => setShowPastEvents(!showPastEvents)} />}
label={translate({ id: "showPastEvents", message: "Show past events" })}
/>
<MultiSelect<CalendarEventCategory>
defaultValues={Object.values(CalendarEventCategory)}
id="release-table-filter-category"
label={translate({ id: "projects", message: "Projects" })}
onChange={(v) => setSelectedCategories(v)}
options={Object.values(CalendarEventCategory)}
/>
<MultiSelect<CalendarEventType>
defaultValues={Object.values(CalendarEventType)}
id="release-table-filter-types"
label={translate({ id: "event", message: "Event" })}
onChange={(v) => setSelectedTypes(v)}
options={Object.values(CalendarEventType)}
/>
</>
)}
<TableContainer>
<TableHead>
<StyledTableRow>
<TableCell>
<Translate id="event">Event</Translate>
</TableCell>
<TableCell>
<Translate id="project">Project</Translate>
</TableCell>
<TableCell>
<Translate id="start">Start</Translate>
</TableCell>
<TableCell>
<Translate id="end">End</Translate>
</TableCell>
<TableCell>
<Translate id="duration">Duration</Translate>
</TableCell>
</StyledTableRow>
</TableHead>
<tbody>
{filteredEvents.map((e, i) => {
const startDate = DateTime.fromISO(e.dates[0]);
const endDate = DateTime.fromISO(e.dates[1]).plus({ days: e.dates[0] === e.dates[0] ? 1 : 0 });
const diff = Interval.fromDateTimes(startDate, endDate);
const duration = diff.toDuration("days").toHuman({ unitDisplay: "narrow" });

return (
<>
{showPastEvents && firstUpcomingEvent?.name === e.name && (
<TableRow className="upcomingEventRow" sx={{ backgroundColor: "success" }} key="upcomingEventRow">
<TableCell colSpan={5} sx={{ backgroundColor: "success" }}>
<Typography fontWeight="bold" textAlign="center">
Current or upcoming
</Typography>
</TableCell>
</TableRow>
)}
<StyledTableRow key={`${e.name}-${i}`}>
<TableCell>
<Stack gap={2}>
<Stack alignItems="center" direction="row" gap={1}>
<EventTypeToIcon t={e.type} />
<Link to={e.url} target="_blank">
<Translate
id="evenTableCellescription"
values={{
rel: `${e.category} ${e.release}`,
type: e.type,
}}
>
{"{type} for {rel}"}
</Translate>
</Link>
</Stack>
</Stack>
</TableCell>
<TableCell>
<CategoryChip c={e.category} />
</TableCell>
<TableCell>{e.dates[0]}</TableCell>
<TableCell>{e.dates[1]}</TableCell>
<TableCell>{duration}</TableCell>
</StyledTableRow>
</>
);
})}
</tbody>
</TableContainer>
</Stack>
);
};

const StyledTableRow = styled(TableRow)(({ theme }) => ({
"&:nth-of-type(even)": {
backgroundColor: theme.palette.action.hover,
},
// hide last border
"&:last-child td, &:last-child th": {
border: 0,
},
}));

export default ThirdPartyReleaseTable;
15 changes: 15 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,18 @@ h3 {
[data-theme="dark"] .OSCard {
box-shadow: var(--ifm-global-shadow-lw);
}

.atcb-button-wrapper,
.atcb-text,
.atcb-button {
box-shadow: none !important;
font-family: "Poppins" !important;
}

.upcomingEventRow {
background-color: var(--ifm-navbar-background-color);
}

.upcomingEventRow .MuiTableCell-root {
border-bottom: 0;
}
4 changes: 2 additions & 2 deletions src/data/supportList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const SupportListData: SupportInfo[] = [
website: "https://endeavouros.com",
},
{
budgieAvailablePostInstall: "10.7.2",
budgieAvailablePostInstall: "10.8",
budgieVersion: "10.7.1",
name: "Fedora Budgie Spin",
showInGrid: true,
Expand Down Expand Up @@ -205,7 +205,7 @@ export const SupportListData: SupportInfo[] = [
website: "https://ubuntubudgie.org",
},
{
budgieAvailablePostInstall: "10.7.2",
budgieAvailablePostInstall: "10.8",
budgieVersion: "10.7.2",
name: "Ultramarine Linux",
summary: () => (
Expand Down
2 changes: 2 additions & 0 deletions src/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ declare module "@mui/material/styles" {
interface MiscColors {
greyish: string;
greydark: string;
dark: string;
lightgrey: string;
purple: string;
white: string;
Expand Down Expand Up @@ -67,6 +68,7 @@ const Theme = createTheme({
misc: {
greyish: "#666666",
greydark: "#333333",
dark: grey[900], // Non-variable unlike primary
lightgrey: "#eeeeee",
purple: "#9f7beb",
white: "#ffffff",
Expand Down
Loading

0 comments on commit 84767b0

Please sign in to comment.