Merged conflicts
This commit is contained in:
@@ -4,57 +4,57 @@ import { Help } from './Help.jsx'
|
||||
import { Icon } from './Icon.jsx'
|
||||
|
||||
export const HamburgerMenu = ({ onClose, mode, setMode, source, setSource, theme, setTheme }) => {
|
||||
return (
|
||||
<div class="menu">
|
||||
<div class="header">
|
||||
<div class="option-group">
|
||||
<button class="flat icon" onClick={onClose}>
|
||||
<Icon name="close" />
|
||||
</button>
|
||||
<button
|
||||
class="icon"
|
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||
>
|
||||
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
|
||||
</button>
|
||||
</div>
|
||||
<div class="item logo">
|
||||
<img src="logo-circuit-board.svg" alt="logo" /> / <span>Orario</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="options">
|
||||
<div class="label">Gruppo Corsi</div>
|
||||
<ComboBox
|
||||
value={source}
|
||||
setValue={setSource}
|
||||
options={[
|
||||
{ value: 'anno-1', label: 'I' },
|
||||
{ value: 'anno-2', label: 'II' },
|
||||
{ value: 'anno-3', label: 'III' },
|
||||
{ value: 'magistrale', label: 'Magistrale' },
|
||||
{ value: 'tutti', label: 'Tutti' },
|
||||
]}
|
||||
/>
|
||||
<div class="label">Visualizzazione</div>
|
||||
<ComboBox
|
||||
value={mode}
|
||||
setValue={setMode}
|
||||
options={[
|
||||
{ value: MODE_COURSE, label: 'Corsi' },
|
||||
{ value: MODE_SCHEDULE, label: 'Giornaliera' },
|
||||
{ value: MODE_WORKWEEK, label: 'Settimana' },
|
||||
return (
|
||||
<div class="menu">
|
||||
<div class="header">
|
||||
<div class="option-group">
|
||||
<button class="flat icon" onClick={onClose}>
|
||||
<Icon name="close" />
|
||||
</button>
|
||||
<button
|
||||
class="icon"
|
||||
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
|
||||
>
|
||||
<Icon name={theme === 'dark' ? 'dark_mode' : 'light_mode'} />
|
||||
</button>
|
||||
</div>
|
||||
<div class="item logo">
|
||||
<img src="logo-circuit-board.svg" alt="logo" /> / <span>Orario</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div class="options">
|
||||
<div class="label">Gruppo Corsi</div>
|
||||
<ComboBox
|
||||
value={source}
|
||||
setValue={setSource}
|
||||
options={[
|
||||
{ value: 'anno-1', label: 'I' },
|
||||
{ value: 'anno-2', label: 'II' },
|
||||
{ value: 'anno-3', label: 'III' },
|
||||
{ value: 'magistrale', label: 'Magistrale' },
|
||||
{ value: 'tutti', label: 'Tutti' },
|
||||
]}
|
||||
/>
|
||||
<div class="label">Visualizzazione</div>
|
||||
<ComboBox
|
||||
value={mode}
|
||||
setValue={setMode}
|
||||
options={[
|
||||
{ value: MODE_COURSE, label: 'Corsi' },
|
||||
{ value: MODE_SCHEDULE, label: 'Giornaliera' },
|
||||
{ value: MODE_WORKWEEK, label: 'Settimana' },
|
||||
{ value: MODE_WORKWEEK_GRID, label: 'Schema' },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="help">
|
||||
<h2>
|
||||
<Icon name="info" />
|
||||
Guida
|
||||
</h2>
|
||||
<Help />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<hr /> */}
|
||||
<div class="help">
|
||||
<h2>
|
||||
<Icon name="info" />
|
||||
Guida
|
||||
</h2>
|
||||
<Help />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { CompoundButton } from './CompoundButton.jsx'
|
||||
import { MODE_COURSE, MODE_SCHEDULE, MODE_WORKWEEK, MODE_WORKWEEK_GRID } from './EventsView.jsx'
|
||||
import { Icon } from './Icon.jsx'
|
||||
|
||||
export const Optionbar = ({ mode, setMode, source, setSource, onHelp }) => {
|
||||
return (
|
||||
<div class="optionbar">
|
||||
<div class="option-group">
|
||||
<div class="item option">
|
||||
<CompoundButton
|
||||
options={[
|
||||
{ value: 'anno-1', label: 'I' },
|
||||
{ value: 'anno-2', label: 'II' },
|
||||
{ value: 'anno-3', label: 'III' },
|
||||
{ value: 'magistrale', label: 'M' },
|
||||
{ value: 'tutti', label: <Icon name="apps" /> },
|
||||
]}
|
||||
value={source}
|
||||
setValue={setSource}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="option-group">
|
||||
<div class="item option">
|
||||
<CompoundButton
|
||||
options={[
|
||||
{ value: MODE_COURSE, label: <Icon name="list" /> },
|
||||
{
|
||||
value: MODE_WORKWEEK_GRID,
|
||||
label: <Icon name="calendar_view_month" />,
|
||||
},
|
||||
{ value: MODE_SCHEDULE, label: <Icon name="calendar_view_day" /> },
|
||||
]}
|
||||
value={mode}
|
||||
setValue={setMode}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
+177
-138
@@ -9,182 +9,221 @@ import { Help } from './components/Help.jsx'
|
||||
import { Icon } from './components/Icon.jsx'
|
||||
import { Popup } from './components/Popup.jsx'
|
||||
import { Toolbar } from './components/Toolbar.jsx'
|
||||
import { Optionbar } from './components/Optionbar.jsx'
|
||||
|
||||
window._ = _
|
||||
window.dataBuffer = {}
|
||||
|
||||
const CALENDAR_IDS = {
|
||||
'anno-1': ['6308cfcb1df5cb026699ce32'],
|
||||
'anno-2': ['6308e2dc09352a0208fefdd9'],
|
||||
'anno-3': ['6308e42a1df5cb026699ced4'],
|
||||
'magistrale': ['6308e8ea0c34e703bb1f7e85'],
|
||||
'tutti': [
|
||||
'6308cfcb1df5cb026699ce32',
|
||||
'6308e2dc09352a0208fefdd9',
|
||||
'6308e42a1df5cb026699ced4',
|
||||
'6308e8ea0c34e703bb1f7e85',
|
||||
],
|
||||
'anno-1': ['6308cfcb1df5cb026699ce32'],
|
||||
'anno-2': ['6308e2dc09352a0208fefdd9'],
|
||||
'anno-3': ['6308e42a1df5cb026699ced4'],
|
||||
'magistrale': ['6308e8ea0c34e703bb1f7e85'],
|
||||
'tutti': [
|
||||
'6308cfcb1df5cb026699ce32',
|
||||
'6308e2dc09352a0208fefdd9',
|
||||
'6308e42a1df5cb026699ced4',
|
||||
'6308e8ea0c34e703bb1f7e85',
|
||||
],
|
||||
}
|
||||
|
||||
async function loadEventi(ids) {
|
||||
const calendari = await Promise.all(
|
||||
ids.map(async id => {
|
||||
// Almost directly copy-pasted from Chrome Dev Tools
|
||||
const req = await fetch(
|
||||
'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
|
||||
{
|
||||
headers: {
|
||||
'content-type': 'application/json;charset=UTF-8',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'same-site',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mostraImpegniAnnullati: true,
|
||||
mostraIndisponibilitaTotali: false,
|
||||
linkCalendarioId: id,
|
||||
clienteId: '628de8b9b63679f193b87046',
|
||||
pianificazioneTemplate: false,
|
||||
dataInizio: '2022-10-02T22:00:00.000Z',
|
||||
dataFine: '2022-10-07T22:00:00.000Z',
|
||||
}),
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
}
|
||||
)
|
||||
const calendari = await Promise.all(
|
||||
ids.map(async id => {
|
||||
// Almost directly copy-pasted from Chrome Dev Tools
|
||||
const req = await fetch(
|
||||
'https://apache.prod.up.cineca.it/api/Impegni/getImpegniCalendarioPubblico',
|
||||
{
|
||||
headers: {
|
||||
'content-type': 'application/json;charset=UTF-8',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'same-site',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mostraImpegniAnnullati: true,
|
||||
mostraIndisponibilitaTotali: false,
|
||||
linkCalendarioId: id,
|
||||
clienteId: '628de8b9b63679f193b87046',
|
||||
pianificazioneTemplate: false,
|
||||
dataInizio: '2022-10-02T22:00:00.000Z',
|
||||
dataFine: '2022-10-07T22:00:00.000Z',
|
||||
}),
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
}
|
||||
)
|
||||
|
||||
return await req.json()
|
||||
})
|
||||
)
|
||||
return await req.json()
|
||||
})
|
||||
)
|
||||
|
||||
<<<<<<< HEAD
|
||||
if (ids.length === 1) {
|
||||
return calendari[0]
|
||||
}
|
||||
=======
|
||||
// console.log(calendari)
|
||||
|
||||
return _.uniqBy(_.concat(...calendari), 'id')
|
||||
if (ids.length === 1) {
|
||||
return calendari[0]
|
||||
}
|
||||
>>>>>>> 41195462f176b27e142a78d7a63c072144135c5a
|
||||
|
||||
return _.uniqBy(_.concat(...calendari), 'id')
|
||||
}
|
||||
|
||||
const App = ({}) => {
|
||||
<<<<<<< HEAD
|
||||
// Data Sources
|
||||
const [source, setSource] = useState('magistrale')
|
||||
const [eventi, setEventi] = useState([])
|
||||
|
||||
// View Modes
|
||||
const [mode, setMode] = useState(MODE_COURSE)
|
||||
=======
|
||||
// Data Sources
|
||||
const [source, setSource] = useState('anno-1')
|
||||
const [eventi, setEventi] = useState([])
|
||||
|
||||
// Selection
|
||||
const [selectedCourses, setSelectedCourses] = useState([])
|
||||
const [hideOtherCourses, setHideOtherCourses] = useState(false)
|
||||
// View Modes
|
||||
const [mode, setMode] = useState(MODE_WORKWEEK_GRID)
|
||||
>>>>>>> 41195462f176b27e142a78d7a63c072144135c5a
|
||||
|
||||
// Menus
|
||||
const [helpVisible, setHelpVisible] = useState(false)
|
||||
const [showMobileMenu, setShowMobileMenu] = useState(false)
|
||||
// Selection
|
||||
const [selectedCourses, setSelectedCourses] = useState([])
|
||||
const [hideOtherCourses, setHideOtherCourses] = useState(false)
|
||||
|
||||
// Menus
|
||||
const [helpVisible, setHelpVisible] = useState(false)
|
||||
const [showMobileMenu, setShowMobileMenu] = useState(false)
|
||||
|
||||
<<<<<<< HEAD
|
||||
useEffect(async () => {
|
||||
const eventi = await loadEventi(CALENDAR_IDS[source])
|
||||
=======
|
||||
useEffect(async () => {
|
||||
console.log('source changed')
|
||||
const eventi = await loadEventi(CALENDAR_IDS[source])
|
||||
>>>>>>> 41195462f176b27e142a78d7a63c072144135c5a
|
||||
|
||||
window.dataBuffer[source] = eventi
|
||||
window.dataBuffer[source] = eventi
|
||||
|
||||
setEventi(eventi)
|
||||
}, [source])
|
||||
setEventi(eventi)
|
||||
}, [source])
|
||||
|
||||
const groupIds = new Set(eventi.map(e => e.nome))
|
||||
const toolOverlayVisible =
|
||||
selectedCourses.length > 0 && selectedCourses.filter(id => groupIds.has(id)).length > 0
|
||||
const groupIds = new Set(eventi.map(e => e.nome))
|
||||
const toolOverlayVisible =
|
||||
selectedCourses.length > 0 && selectedCourses.filter(id => groupIds.has(id)).length > 0
|
||||
|
||||
<<<<<<< HEAD
|
||||
useEffect(() => {
|
||||
const groupIds = new Set(eventi.map(e => e.nome))
|
||||
=======
|
||||
useEffect(() => {
|
||||
console.log('course length changed')
|
||||
const groupIds = new Set(eventi.map(e => e.nome))
|
||||
>>>>>>> 41195462f176b27e142a78d7a63c072144135c5a
|
||||
|
||||
if (
|
||||
selectedCourses.length === 0 ||
|
||||
selectedCourses.filter(id => groupIds.has(id)).length === 0
|
||||
) {
|
||||
setHideOtherCourses(false)
|
||||
}
|
||||
}, [eventi, selectedCourses.length])
|
||||
if (
|
||||
selectedCourses.length === 0 ||
|
||||
selectedCourses.filter(id => groupIds.has(id)).length === 0
|
||||
) {
|
||||
setHideOtherCourses(false)
|
||||
}
|
||||
}, [eventi, selectedCourses.length])
|
||||
|
||||
const [theme, setTheme] = useState(
|
||||
localStorage.getItem('theme') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
)
|
||||
const [theme, setTheme] = useState(
|
||||
localStorage.getItem('theme') ??
|
||||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
||||
)
|
||||
|
||||
document.body.classList.toggle('dark-mode', theme === 'dark')
|
||||
localStorage.setItem('theme', theme)
|
||||
document.body.classList.toggle('dark-mode', theme === 'dark')
|
||||
localStorage.setItem('theme', theme)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Toolbar
|
||||
{...{
|
||||
mode,
|
||||
setMode,
|
||||
source,
|
||||
setSource,
|
||||
onShowMenu: () => setShowMobileMenu(true),
|
||||
onHelp: () => setHelpVisible(true),
|
||||
theme,
|
||||
setTheme,
|
||||
}}
|
||||
/>
|
||||
<EventsView
|
||||
mode={mode}
|
||||
selection={selectedCourses}
|
||||
setSelection={setSelectedCourses}
|
||||
hideOtherCourses={hideOtherCourses}
|
||||
start={new Date(2022, 10, 3)}
|
||||
events={eventi.map(({ nome, dataInizio, dataFine, docenti, aule }) => ({
|
||||
id: nome,
|
||||
name: _.split(nome, '-', 1)[0].trim(),
|
||||
start: new Date(dataInizio),
|
||||
end: new Date(dataFine),
|
||||
docenti: docenti.map(({ nome, cognome }) =>
|
||||
_.startCase(_.lowerCase(nome) + ' ' + _.lowerCase(cognome))
|
||||
),
|
||||
aula: _.startCase(aule[0].codice.toLowerCase()).replace(
|
||||
/([A-Z]) ([1-9])/,
|
||||
'$1$2'
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
{toolOverlayVisible && (
|
||||
<ToolOverlay
|
||||
visibility={hideOtherCourses}
|
||||
toggleVisibility={() => setHideOtherCourses(s => !s)}
|
||||
onClose={() => {
|
||||
setSelectedCourses([])
|
||||
setHideOtherCourses(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showMobileMenu && (
|
||||
<HamburgerMenu
|
||||
{...{
|
||||
mode,
|
||||
setMode,
|
||||
source,
|
||||
setSource,
|
||||
theme,
|
||||
setTheme,
|
||||
onClose: () => {
|
||||
setShowMobileMenu(false)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{helpVisible && (
|
||||
<Popup
|
||||
title={
|
||||
<>
|
||||
<Icon name="info" /> Guida
|
||||
</>
|
||||
}
|
||||
onClose={() => setHelpVisible(false)}
|
||||
>
|
||||
<Help />
|
||||
</Popup>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
return (
|
||||
<>
|
||||
<Toolbar
|
||||
{...{
|
||||
mode,
|
||||
setMode,
|
||||
source,
|
||||
setSource,
|
||||
onShowMenu: () => setShowMobileMenu(true),
|
||||
onHelp: () => setHelpVisible(true),
|
||||
theme,
|
||||
setTheme,
|
||||
}}
|
||||
/>
|
||||
<Optionbar
|
||||
{...{
|
||||
mode,
|
||||
setMode,
|
||||
source,
|
||||
setSource,
|
||||
onHelp: () => setHelpVisible(true),
|
||||
}}
|
||||
/>
|
||||
<EventsView
|
||||
mode={mode}
|
||||
selection={selectedCourses}
|
||||
setSelection={setSelectedCourses}
|
||||
hideOtherCourses={hideOtherCourses}
|
||||
start={new Date(2022, 10, 3)}
|
||||
events={eventi.map(({ nome, dataInizio, dataFine, docenti, aule }) => ({
|
||||
id: nome,
|
||||
name: _.split(nome, '-', 1)[0].trim(),
|
||||
start: new Date(dataInizio),
|
||||
end: new Date(dataFine),
|
||||
docenti: docenti.map(({ nome, cognome }) =>
|
||||
_.startCase(_.lowerCase(nome) + ' ' + _.lowerCase(cognome))
|
||||
),
|
||||
aula: _.startCase(aule[0].codice.toLowerCase()).replace(
|
||||
/([A-Z]) ([1-9])/,
|
||||
'$1$2'
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
{toolOverlayVisible && (
|
||||
<ToolOverlay
|
||||
visibility={hideOtherCourses}
|
||||
toggleVisibility={() => setHideOtherCourses(s => !s)}
|
||||
onClose={() => {
|
||||
setSelectedCourses([])
|
||||
setHideOtherCourses(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{showMobileMenu && (
|
||||
<HamburgerMenu
|
||||
{...{
|
||||
mode,
|
||||
setMode,
|
||||
source,
|
||||
setSource,
|
||||
theme,
|
||||
setTheme,
|
||||
onClose: () => {
|
||||
setShowMobileMenu(false)
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{helpVisible && (
|
||||
<Popup
|
||||
title={
|
||||
<>
|
||||
<Icon name="info" /> Guida
|
||||
</>
|
||||
}
|
||||
onClose={() => setHelpVisible(false)}
|
||||
>
|
||||
<Help />
|
||||
</Popup>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
render(<App />, document.body)
|
||||
|
||||
@@ -448,9 +448,38 @@ body {
|
||||
}
|
||||
}
|
||||
}
|
||||
.optionbar {
|
||||
@extend .panel;
|
||||
|
||||
padding: 1rem 0.75rem 1rem 1rem;
|
||||
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid var(--border-500);
|
||||
|
||||
height: 4rem;
|
||||
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
@media screen and (max-width: $device-s-width), (pointer: coarse) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.option-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
gap: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
.events-view {
|
||||
height: calc(100vh - 4rem);
|
||||
@media screen and (max-width: $device-s-width), (pointer: coarse) {
|
||||
height: calc(100vh - 8rem);
|
||||
}
|
||||
|
||||
.course-view {
|
||||
padding: 1rem;
|
||||
|
||||
Reference in New Issue
Block a user