lodash#groupBy JavaScript Examples
The following examples show how to use
lodash#groupBy.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.js From hzero-front with Apache License 2.0 | 6 votes |
/**
* 渲染执行器
* @param {array} data - 执行器数据
* @param {string} type - 初始化类型
*/
@Bind()
renderProcessors(data, type) {
if (data) {
const levelData = groupBy(data, 'orderSeq');
const processorsContent = [];
Object.keys(levelData).forEach(key => {
const processors = this.squareWrapper(levelData[key]);
if (type === 'post') processorsContent.push(this.line());
processorsContent.push(processors);
if (type === 'pre') processorsContent.push(this.line());
});
return processorsContent;
}
}
Example #2
Source File: Chart.js From covid19 with MIT License | 6 votes |
calculateDayOffsets = (sortedDailyCounts = [], benchmarkCountryISO) => {
const countryBenchmark = benchmarkCountryISO
const countryCounts = groupBy(sortedDailyCounts, 'country.iso')
const benchmarkCounts = countryCounts[countryBenchmark] || []
const revBenchmarkCounts = reverse(benchmarkCounts)
let countries = {}
revBenchmarkCounts.forEach((count, i) => {
if (i == revBenchmarkCounts.length - 1) return
const currentCount = count
const previousCount = revBenchmarkCounts[i + 1]
for (const country in countryCounts) {
const counts = countryCounts[country]
counts.forEach((count) => {
if (countries[country]) return
if (
count.totalCases < currentCount.totalCases &&
count.totalCases > previousCount.totalCases
) {
countries[country] = daysBetween(
new Date(currentCount.date.date),
new Date(count.date.date)
)
}
})
}
})
return countries
}
Example #3
Source File: data.js From covid19-dashboard with MIT License | 6 votes |
export function reportToGeoJSON(report, date) {
const byCode = groupBy(report.history, 'code')
return {
type: 'FeatureCollection',
features: Object.keys(byCode).filter(code => Boolean(geo[code].center)).map(code => {
const selectedDateAvailable = byCode[code].find(r => r.date === date)
const properties = selectedDateAvailable ? selectedDateAvailable : {code}
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: geo[code].center
},
properties: {
...properties,
...byCode[code].find(r => r.date === date),
history: byCode[code].filter(r => date >= r.date)
}
}
}).filter(i => Boolean(i))
}
}
Example #4
Source File: node-details-table.js From ThreatMapper with Apache License 2.0 | 6 votes |
function getSortedNodes(nodes, sortedByHeader, sortedDesc) {
const getValue = getValueForSortedBy(sortedByHeader);
const withAndWithoutValues = groupBy(nodes, (n) => {
if (!n || n.valueEmpty) {
return 'withoutValues';
}
const v = getValue(n);
return v !== null && v !== undefined ? 'withValues' : 'withoutValues';
});
const withValues = sortNodes(withAndWithoutValues.withValues, getValue, sortedDesc);
const withoutValues = sortNodes(withAndWithoutValues.withoutValues, getValue, sortedDesc);
return concat(withValues, withoutValues);
}
Example #5
Source File: workflows.js From holo-schedule with MIT License | 6 votes |
syncHotnesses = async (lives = []) => {
if (lives.length === 0) {
return
}
const hotnessesByLiveId = groupBy(await getHotnessesOfLives(lives, { limit: 1000 }), 'live_id')
await store.set({
[ENDED_LIVES]: (getCachedEndedLives() ?? []).map(live => {
if (live['id'] in hotnessesByLiveId) {
return { ...live, hotnesses: hotnessesByLiveId[live['id']] }
}
return live
}),
})
}
Example #6
Source File: summary-charts.js From website with Apache License 2.0 | 6 votes |
generateAnnotationNumbers = annotations => {
const splitAnnotations = groupBy(annotations, a => a.dataElement)
let asciiCode = 'A'.charCodeAt(0)
const generateForField = field => {
if (splitAnnotations[field]) {
splitAnnotations[field] = splitAnnotations[field].map(a => ({
...a,
date: parseDate(a.date),
annotationSymbol: String.fromCharCode(asciiCode++),
}))
}
}
;['tests', 'cases', 'hospitalizations', 'death'].forEach(generateForField) // death is the only non-plural on contentful
return splitAnnotations
}
Example #7
Source File: node-details-table-row.js From ThreatMapper with Apache License 2.0 | 6 votes |
function getValuesForNode(node) {
let values = {};
['metrics', 'metadata'].forEach((collection) => {
if (node[collection]) {
node[collection].forEach((field) => {
const result = Object.assign({}, field);
result.valueType = collection;
values[field.id] = result;
});
}
});
if (node.parents) {
const byTopologyId = groupBy(node.parents, parent => parent.topologyId);
const relativesByTopologyId = mapValues(byTopologyId, (relatives, topologyId) => ({
id: topologyId,
label: topologyId,
relatives,
value: relatives.map(relative => relative.label).join(', '),
valueType: 'relatives',
}));
values = {
...values,
...relativesByTopologyId,
};
}
return values;
}
Example #8
Source File: node-details-table.js From ThreatMapper with Apache License 2.0 | 6 votes |
function getSortedNodes(nodes, sortedByHeader, sortedDesc) {
const getValue = getValueForSortedBy(sortedByHeader);
const withAndWithoutValues = groupBy(nodes, (n) => {
if (!n || n.valueEmpty) {
return 'withoutValues';
}
const v = getValue(n);
return v !== null && v !== undefined ? 'withValues' : 'withoutValues';
});
const withValues = sortNodes(withAndWithoutValues.withValues, getValue, sortedDesc);
const withoutValues = sortNodes(withAndWithoutValues.withoutValues, getValue, sortedDesc);
return concat(withValues, withoutValues);
}
Example #9
Source File: index.js From hzero-front with Apache License 2.0 | 5 votes |
render() {
const {
tenantInitLog: { logList, pagination, enumMap, picData },
listLoading,
picLoading = false,
} = this.props;
const { currentLog, isShowImg } = this.state;
let imgData = {};
if (!isEmpty(picData)) {
imgData = groupBy(orderBy(picData, 'orderSeq'), 'processorType');
}
const filterProps = {
onSearch: this.handleSearch,
onRef: this.handleBindRef,
enumMap,
};
const listProps = {
isShowImg,
dataSource: logList,
pagination,
picProps: {
dataSource: imgData,
loading: picLoading,
type: !isEmpty(currentLog) && currentLog.initType.toLowerCase(),
},
loading: listLoading,
onChange: this.handleSearch,
onSearchPic: this.handleSearchPic,
onOpenPic: this.handleOpenImgModal,
onClosePic: this.handleCloseImgModal,
};
return (
<>
<Header title={intl.get(`${viewTitle}.tenant.init.log`).d('租户初始化处理日志')} />
<Content>
<FilterForm {...filterProps} />
<ListTable {...listProps} />
</Content>
</>
);
}
Example #10
Source File: dragAndDrop.js From OctoFarm with GNU Affero General Public License v3.0 | 5 votes |
export function dragAndDropGroupEnable(printers) {
const groupedPrinters = mapValues(groupBy(printers, "group"));
for (const key in groupedPrinters) {
if (groupedPrinters.hasOwnProperty(key)) {
if (key !== "") {
const currentGroupEncoded = encodeURIComponent(key);
const dropArea = document.getElementById(
`dropPanel-${currentGroupEncoded}`
);
// Prevent default drag behaviors
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
dropArea.addEventListener(eventName, preventDefaults, false);
document.body.addEventListener(eventName, preventDefaults, false);
});
// Highlight drop area when item is dragged over it
["dragenter", "dragover"].forEach((eventName) => {
dropArea.addEventListener(
eventName,
(event) => {
activeFile = true;
highlight(event, dropArea);
},
false
);
});
["dragleave", "drop"].forEach((eventName) => {
dropArea.addEventListener(
eventName,
(event) => {
activeFile = false;
unhighlight(event, dropArea);
},
false
);
});
dropArea.addEventListener(
"drop",
(event) => {
handleMassDrop(event, groupedPrinters[key]);
},
false
);
}
}
}
}
Example #11
Source File: ChartData.js From powir with GNU General Public License v3.0 | 5 votes |
function getGroupedPowerUsageInfoData(info) {
let formattedData = info.data.reduce((data, item, index) => {
function getDuration(pastItem, currentItem, futureItem) {
function getDateObject(dateString) {
return new Date(dateString)
}
function getMidnightDateTime(date) {
return new Date(date.toUTCString()).setHours(0, 0, 0, 0)
}
function getReturnItem(item, duration) {
return [
item[0].split(" ")[0],
item[0].split(" ")[1],
duration / 1000 / 60,
item[1],
item[2]
]
}
let past = getDateObject(pastItem[0])
let current = getDateObject(currentItem[0])
let future = getDateObject(futureItem[0])
if (past.getDate() === current.getDate()) {
if (future.getDate() === current.getDate()) {
return [getReturnItem(currentItem, (future - current))]
}
return [getReturnItem(currentItem, (getMidnightDateTime(future) - current))]
}
else {
if (future.getDate() === current.getDate()) {
return [[
currentItem[0].split(" ")[0],
"0:00:00",
(current - getMidnightDateTime(current)) / 1000 / 60,
'suspended',
null
],
getReturnItem(currentItem, (future - current))
]
}
return [[
currentItem[0].split(" ")[0],
"0:00:00",
(current - getMidnightDateTime(current)) / 1000 / 60,
'suspended',
null
],
getReturnItem(currentItem, (getMidnightDateTime(future) - current))
]
}
}
switch (index) {
case info.data.length-1:
return data
case 0:
return data
default:
let durations = getDuration(
info.data[index-1],
item,
info.data[index+1]
)
durations.map(duration => data.push(duration))
return data
}
}, [])
return groupBy(formattedData, 0)
}
Example #12
Source File: index.js From datapass with GNU Affero General Public License v3.0 | 5 votes |
UserEnrollmentList = () => {
const [isLoading, setIsLoading] = useState(true);
const [enrollmentsByOrganization, setEnrollmentsByOrganization] = useState();
const { goToItem } = useListItemNavigation();
useEffect(() => {
const onFetchData = async () => {
setIsLoading(true);
const enrollments = await getUserEnrollments();
const enrollmentsByOrganization = groupBy(enrollments, (e) => e.siret);
setEnrollmentsByOrganization(enrollmentsByOrganization);
setIsLoading(false);
};
onFetchData();
}, []);
return (
<main className="list-page">
<ListHeader title="Toutes mes habilitations">
<NewEnrollmentButton />
</ListHeader>
{isLoading && (
<div className="full-page">
<Loader />
</div>
)}
{!isLoading && isEmpty(enrollmentsByOrganization) && (
<div className="full-page">
<Alert title="Vous n’avez aucune habilitation" />
</div>
)}
{!isLoading && !isEmpty(enrollmentsByOrganization) && (
<div className="page-container list-container">
{Object.keys(enrollmentsByOrganization).map((group) => (
<React.Fragment key={group}>
<div className="list-title fr-text--lead">
{enrollmentsByOrganization[group][0].nom_raison_sociale}
</div>
{enrollmentsByOrganization[group].map((enrollment) => (
<Enrollment
key={enrollment.id}
{...enrollment}
onSelect={goToItem}
/>
))}
</React.Fragment>
))}
</div>
)}
</main>
);
}
Example #13
Source File: node-details-table-row.js From ThreatMapper with Apache License 2.0 | 5 votes |
function getValuesForNode(node) {
let values = {};
['metrics', 'metadata'].forEach(collection => {
if (node[collection]) {
node[collection].forEach(field => {
const result = { ...field };
result.valueType = collection;
if (field.id === 'captureStatus') {
const interfaceList =
node[collection].filter(row => row.id === 'interfaceNames') || [];
const { value = '' } = result;
const match = value.match(/--input-raw ([^\s]+)/gm);
let interfaceName = '';
if (match && match.length >= 1) {
const tempInterfaceName = match[0].split(' ')[1];
const interfaceListArr = interfaceList[0].value || '';
if (
tempInterfaceName.trim().toLowerCase() === 'any' ||
interfaceListArr.split(';').includes(tempInterfaceName)
) {
interfaceName = tempInterfaceName;
}
}
let captureStatusValue = 'Inactive';
if (interfaceName) {
captureStatusValue =
interfaceName.trim().toLowerCase() !== 'any'
? `Active on ${interfaceName} interface`
: 'Active on all interfaces';
}
values[field.id] = { ...result, value: captureStatusValue };
} else if (field.id === 'user_defined_tags') {
values[field.id] = {
...result,
value: <TagModalTrigger value={result.value} node={node} />,
};
} else if (field.id === 'cloud_provider') {
values[field.id] = {
...result,
value: result.value || 'Private/On Prem',
};
} else {
values[field.id] = result;
}
});
}
});
if (node.parents) {
const byTopologyId = groupBy(node.parents, parent => parent.topologyId);
const relativesByTopologyId = mapValues(
byTopologyId,
(relatives, topologyId) => ({
id: topologyId,
label: topologyId,
value: relatives.map(relative => relative.label).join(', '),
valueType: 'relatives',
relatives,
})
);
values = {
...values,
...relativesByTopologyId,
};
}
return values;
}
Example #14
Source File: index.js From datapass with GNU Affero General Public License v3.0 | 4 votes |
DonneesSection = ({
DonneesDescription,
availableScopes = [],
AvailableScopesDescription,
accessModes,
enableFileSubmissionForScopeSelection = false,
}) => {
const {
disabled,
onChange,
enrollment: {
scopes = {},
data_recipients = '',
data_retention_period = '',
data_retention_comment = '',
additional_content = {},
documents = [],
documents_attributes = [],
},
} = useContext(FormContext);
useEffect(() => {
if (!isEmpty(availableScopes) && isEmpty(scopes)) {
onChange({
target: {
name: 'scopes',
value: zipObject(
availableScopes.map(({ value }) => value),
availableScopes.map(
({ required, checkedByDefault }) =>
!!required || !!checkedByDefault
)
),
},
});
}
});
const groupTitleScopesGroup = groupBy(
availableScopes,
(e) => e.groupTitle || 'default'
);
// {'a': true, 'b': false, 'c': true} becomes ['a', 'c']
const scopesAsArray = chain(scopes)
.omitBy((e) => !e)
.keys()
.value();
const availableScopesAsArray = availableScopes.map(({ value }) => value);
const outdatedScopes = difference(scopesAsArray, availableScopesAsArray);
const [isFileInputExpanded, setFileInputExpanded] = useState(
enableFileSubmissionForScopeSelection &&
!isEmpty(
documents.filter(
({ type }) => type === 'Document::ExpressionBesoinSpecifique'
)
)
);
useEffect(() => {
const hasDocument = !isEmpty(
documents.filter(
({ type }) => type === 'Document::ExpressionBesoinSpecifique'
)
);
if (
enableFileSubmissionForScopeSelection &&
!isFileInputExpanded &&
hasDocument
) {
setFileInputExpanded(true);
}
}, [enableFileSubmissionForScopeSelection, isFileInputExpanded, documents]);
return (
<ScrollablePanel scrollableId={SECTION_ID}>
<h2>Les données nécessaires</h2>
{DonneesDescription && (
<ExpandableQuote title="Comment choisir les données ?">
<DonneesDescription />
</ExpandableQuote>
)}
{AvailableScopesDescription && <AvailableScopesDescription />}
{!isEmpty(availableScopes) && (
<>
<h3>À quelles données souhaitez-vous avoir accès ?</h3>
{Object.keys(groupTitleScopesGroup).map((group) => (
<Scopes
key={group}
title={group === 'default' ? null : group}
scopes={groupTitleScopesGroup[group]}
selectedScopes={scopes}
disabledApplication={disabled}
handleChange={onChange}
/>
))}
{disabled && !isEmpty(outdatedScopes) && (
<Scopes
title="Les données suivantes ont été sélectionnées mais ne sont plus disponibles :"
scopes={outdatedScopes.map((value) => ({ value, label: value }))}
selectedScopes={zipObject(
outdatedScopes,
Array(outdatedScopes.length).fill(true)
)}
disabledApplication
handleChange={() => null}
/>
)}
</>
)}
{enableFileSubmissionForScopeSelection && (
<>
<ExpandableQuote title="J’ai une expression de besoin spécifique ?">
<p>
Les partenaires ayant convenu avec la DGFiP un périmètre de
données particulier peuvent rattacher leur expression de besoin
listant l’ensemble des données strictement nécessaires à leur cas
d’usage. Si vous n'avez pas encore contacté la DGFiP, vous pouvez
les joindre à l'adresse{' '}
<Link
inline
href="mailto:[email protected]?subject=Expression%20de%20besoin%20spécifique"
>
[email protected]
</Link>
</p>
<CheckboxInput
label="J’ai une expression de besoin spécifique"
value={isFileInputExpanded}
onChange={() => setFileInputExpanded(!isFileInputExpanded)}
disabled={disabled}
/>
</ExpandableQuote>
{isFileInputExpanded && (
<>
<FileInput
label="Joindre l’expression de besoin"
meta={
'Attention : seule l’expression de besoin en données ayant déjà été partagée avec la DGFiP peut être rattachée à votre habilitation.'
}
mimeTypes="*"
disabled={disabled}
uploadedDocuments={documents}
documentsToUpload={documents_attributes}
documentType={'Document::ExpressionBesoinSpecifique'}
onChange={onChange}
/>
</>
)}
</>
)}
{!isEmpty(accessModes) && (
<>
<h3>Comment souhaitez-vous y accéder ?</h3>
{accessModes.map(({ id, label }) => (
<CheckboxInput
key={id}
label={label}
name={`additional_content.${id}`}
value={additional_content[id] || false}
disabled={disabled}
onChange={onChange}
/>
))}
</>
)}
<h3>Comment seront traitées ces données personnelles ?</h3>
<TextInput
label="Destinataires des données"
placeholder={
'« agents instructeurs des demandes d’aides », « usagers des ' +
'services publics de la ville », etc.'
}
meta={
<Link
inline
newTab
href="https://www.cnil.fr/fr/definition/destinataire"
aria-label="Voir la définition CNIL du destinataire des données"
>
Plus d’infos
</Link>
}
name="data_recipients"
value={data_recipients}
disabled={disabled}
onChange={onChange}
required
/>
<NumberInput
label="Durée de conservation des données en mois"
meta={
<Link
inline
newTab
href="https://www.cnil.fr/fr/les-durees-de-conservation-des-donnees"
aria-label="Voir l’explication CNIL sur les durées de conservation des données"
>
Plus d’infos
</Link>
}
name="data_retention_period"
value={data_retention_period}
disabled={disabled}
onChange={onChange}
required
/>
{data_retention_period > 36 && (
<>
<Alert type="warning" title="Attention">
Cette durée excède la durée communément constatée (36 mois).
</Alert>
<TextInput
label="Veuillez justifier cette durée dans le champ ci-après :"
name="data_retention_comment"
value={data_retention_comment}
disabled={disabled}
onChange={onChange}
/>
</>
)}
</ScrollablePanel>
);
}
Example #15
Source File: Chart.js From covid19 with MIT License | 4 votes |
Chart = ({
dailyCounts = [],
countries = [],
enabledCountries,
defaultCountry
// log
}) => {
// sort dailyCounts for all later operations
const sortedDailyCounts = orderBy(dailyCounts, 'date.date')
const offsets = calculateDayOffsets(sortedDailyCounts, defaultCountry)
const offsetDailyCounts = sortedDailyCounts.map((origCount) => {
// deep clone
let count = JSON.parse(JSON.stringify(origCount))
let offset = offsets[count.country.iso]
if (!offset) {
return count
} // in case of benchmark
let newDate = addDays(new Date(count.date.date), offset)
// round date to the nearest day
let offsetForRounded = new Date(newDate.getTime() + 12 * 60 * 60)
let roundedDate = new Date(
offsetForRounded.getFullYear(),
offsetForRounded.getMonth(),
offsetForRounded.getDate()
)
// extract the YYYY-DD-MM portion
count.date.date = new Date(
roundedDate.toISOString().substring(0, 10)
).toISOString()
return count
})
const sortedOffsetDailyCounts = orderBy(offsetDailyCounts, 'date.date')
// Assemble chart display
let days = {}
sortedOffsetDailyCounts.forEach((count) => {
days[count.date.date] = days[count.date.date] || {}
days[count.date.date][`${count.country.iso}TotalCases`] = count.totalCases
days[count.date.date][`${count.country.iso}TotalDeaths`] = count.totalDeaths
})
const countryCounts = groupBy(sortedDailyCounts, 'country.iso')
// Highest date in benchmark country
const maxBenchmarkDate = last(countryCounts[defaultCountry]).date.date
// Calculate X axis numbers to show how many days ahead / behind a country is
for (const day in days) {
const daysBehind = daysBetween(new Date(day), new Date(maxBenchmarkDate))
days[day]['daysBehind'] = daysBehind
}
const behindOrAhead =
(last(Object.values(days))?.daysBehind || -1) > 0 ? 'ahead of' : 'behind'
let updated = new Date(last(countryCounts[defaultCountry]).date.createdAt)
updated.setDate(updated.getDate() + 1) // JS dates suck
updated = updated
.toLocaleDateString()
.replace('/2020', '')
.replace('2020-', '')
// Prepare chart data
const [chartData, setChartData] = useState([])
useEffect(() => {
setChartData(
Object.keys(days).map((day) => ({
date: day,
...days[day]
}))
)
}, [dailyCounts])
// Sorting
useEffect(() => {
setChartData((chartData) => orderBy(chartData, 'date'))
}, [dailyCounts])
return (
<ResponsiveContainer height={512} id="primary">
<LineChart
data={chartData}
margin={{ top: 0, right: 10, bottom: 25, left: 15 }}
>
<XAxis
dataKey="daysBehind"
label={{
value: `Days ${behindOrAhead} ${countryFromKey(
defaultCountry,
countries
)} (last updated: ${updated})`,
position: 'bottom'
}}
/>
<YAxis
tickFormatter={yAxisFormatter}
label={{
value: 'Total COVID-19 Cases',
angle: -90,
position: 'left'
}}
/>
<Tooltip
separator=": "
formatter={(value, key) => [
commaNumber(value),
countryFromKey(key, countries)
]}
/>
<CartesianGrid stroke={theme.colors.snow} strokeDasharray="8 8" />
{enabledCountries.map((iso) => (
<Line
key={iso}
type="monotone"
dataKey={`${iso}TotalCases`}
stroke={theme.colors[iso]}
strokeWidth={defaultCountry === iso ? 6 : 3}
dot={false}
activeDot={{ r: 8 }}
connectNulls
/>
))}
<style>{`
.recharts-label {
fill: ${theme.colors.muted};
}
.recharts-default-tooltip {
border-radius: 0.375rem;
}
.recharts-tooltip-label {
color: ${theme.colors.muted};
font-family: ${theme.fonts.sans};
font-size: 2rem;
line-height: 1.5;
}
#primary .recharts-tooltip-label:after {
content: ' days';
}
#primary .recharts-tooltip-item {
font-family: ${theme.fonts.serif};
font-size: 1rem;
}
@media (prefers-color-scheme: dark) {
.recharts-default-tooltip {
background-color: #1e1e1e !important;
}
.recharts-label {
fill: ${theme.colors.snow};
}
.recharts-tooltip-label {
color: ${theme.colors.snow};
}
.recharts-layer:not(.recharts-active-dot) .recharts-dot {
fill: #1e1e1e !important;
}
line.recharts-cartesian-axis-line,
line.recharts-cartesian-axis-tick-line,
.recharts-cartesian-grid line {
opacity: 0.25 !important;
}
}
`}</style>
</LineChart>
</ResponsiveContainer>
)
}
Example #16
Source File: ChartData.js From powir with GNU General Public License v3.0 | 4 votes |
function createBatteryLifeHistoryData(info) {
function getDaysInMonth(date) {
return new Date(date.getFullYear(), date.getMonth()+1, 0).getDate()
}
function chooseDate(date) {
let [start_date, end_date] = date.split(" - ")
if (getDaysInMonth(new Date(start_date)) - new Date(start_date).getDate() > new Date(end_date).getDate()) {
return start_date.split("-").slice(0, 2).join("")
}
return end_date.split("-").slice(0, 2).join("")
}
function filterOutliers(array) {
/*
* Reference: https://www.mathworks.com/matlabcentral/cody/problems/42485-eliminate-outliers-using-interquartile-range
* Following this approach except we aren't repeating the IQR and elimination process after every step.
* */
// Then sort
// noinspection JSValidateTypes
if (array.length < 4) {
return {
data: array,
indexes: []
}
}
// noinspection JSValidateTypes
let values = sortBy(array)
/* Then find a generous IQR. This is generous because if (values.length / 4)
* is not an int, then really you should average the two elements on either
* side to find q1.
*/
let q1 = values[Math.floor((values.length / 4))]
// Likewise for q3.
let q3 = values[Math.ceil((values.length * (3 / 4)))]
let iqr = q3 - q1;
// Then find min and max values
let maxValue = q3 + iqr*1.5;
// Then reduce anything beyond or beneath these values.
return array.reduce((data, item, index) => {
if (item <= maxValue) {
data.indexes.push(index)
data.data.push(item)
return data
}
return data
}, {
data: [],
indexes: []
})
}
function averageDatasetByMonth(value, index) {
return value.reduce((data, element) => {
data += element[index]
return data
}, 0) / value.length
}
let formattedInfo = groupBy(info.data.reduce((data, item) => {
if (item[1] === "0:00:00" || item[3] === "0:00:00") {
return data
}
data.push([
chooseDate(item[0]),
Number(item[1].split(":")[0])*60 + Number(item[1].split(":")[1]),
Number(item[3].split(":")[0])*60 + Number(item[3].split(":")[1]),
])
return data
}, []), 0)
let activeDataset = []
let designDataset = []
for (let [, value] of Object.entries(formattedInfo)) {
activeDataset.push(averageDatasetByMonth(value, 1))
designDataset.push(averageDatasetByMonth(value, 2))
}
let filteredDataset = filterOutliers(activeDataset)
let filteredActiveDataset = filterOutliers(activeDataset).data
let filteredDesignDataset = designDataset.filter((item, index) => filteredDataset.indexes.includes(index))
let labelsDataset = Object.keys(formattedInfo).reduce((data, item, index) => {
if (filteredDataset.indexes.includes(index)) {
data.push(item.slice(0, 4) + "/" + item.slice(4, 6))
return data
}
return data
}, [])
return {
labels: labelsDataset,
datasets: [{
label: info.keys[1],
backgroundColor: 'red',
borderColor: 'red',
data: filteredActiveDataset,
fill: false,
}, {
label: info.keys[3],
backgroundColor: 'blue',
borderColor: 'blue',
data: filteredDesignDataset,
fill: false,
}]
}
}
Example #17
Source File: FederatedResults.js From sampo-ui with MIT License | 4 votes |
FederatedResults = props => {
const { rootUrl, perspective, screenSize, clientFSState, layoutConfig, portalConfig } = props
const { searchMode } = perspective
const perspectiveID = perspective.id
const { maps } = clientFSState
const { mapClusters, mapMarkers } = maps
const layerControlExpanded = screenSize === 'md' ||
screenSize === 'lg' ||
screenSize === 'xl'
let groupedResults = []
if (props.location.pathname.endsWith('statistics')) {
const grouped = groupBy(props.clientFSResults, clientFSState.groupBy)
for (const key in grouped) {
groupedResults.push({
category: key,
prefLabel: key,
instanceCount: grouped[key].length
})
}
groupedResults = orderBy(groupedResults, 'instanceCount', 'desc')
}
return (
<>
<PerspectiveTabs
tabs={perspective.tabs}
screenSize={props.screenSize}
layoutConfig={layoutConfig}
/>
<Route
exact path={`${rootUrl}/${perspectiveID}/${searchMode}`}
render={() => <Redirect to={`${rootUrl}/${perspectiveID}/${searchMode}/table`} />}
/>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/table`}>
<VirtualizedTable
portalConfig={portalConfig}
list={Immutable.List(props.clientFSResults)}
clientFSState={props.clientFSState}
clientFSSortResults={props.clientFSSortResults}
perspectiveID={perspectiveID}
layoutConfig={layoutConfig}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_clusters`}>
<LeafletMap
portalConfig={portalConfig}
perspectiveConfig={perspective}
center={mapClusters.center}
zoom={mapClusters.zoom}
results={props.clientFSResults}
leafletMapState={props.leafletMapState}
resultClass='mapClusters'
pageType='clientFSResults'
mapMode='cluster'
createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
fetchResults={props.fetchResults}
fetchGeoJSONLayers={props.fetchGeoJSONLayers}
clearGeoJSONLayers={props.clearGeoJSONLayers}
fetchByURI={props.fetchByURI}
fetching={false}
showInstanceCountInClusters={false}
updateFacetOption={props.updateFacetOption}
showError={props.showError}
showExternalLayers
layerControlExpanded={layerControlExpanded}
layerConfigs={props.leafletConfig.layerConfigs}
updateMapBounds={props.updateMapBounds}
layoutConfig={layoutConfig}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/map_markers`}>
{props.clientFSResults.length < 500
? (
<LeafletMap
portalConfig={portalConfig}
perspectiveConfig={perspective}
center={mapMarkers.center}
zoom={mapMarkers.zoom}
results={props.clientFSResults}
leafletMapState={props.leafletMapState}
resultClass='mapMarkers'
pageType='clientFSResults'
mapMode='marker'
createPopUpContent={props.leafletConfig.createPopUpContentNameSampo}
fetchResults={props.fetchResults}
fetchGeoJSONLayers={props.fetchGeoJSONLayers}
clearGeoJSONLayers={props.clearGeoJSONLayers}
fetchByURI={props.fetchByURI}
fetching={false}
showInstanceCountInClusters={false}
updateFacetOption={props.updateFacetOption}
showError={props.showError}
showExternalLayers
layerControlExpanded={layerControlExpanded}
layerConfigs={props.leafletConfig.layerConfigs}
updateMapBounds={props.updateMapBounds}
layoutConfig={layoutConfig}
/>
)
: <ResultInfo message={intl.get('leafletMap.tooManyResults')} />}
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/statistics`}>
<ApexCharts
portalConfig={portalConfig}
layoutConfig={layoutConfig}
perspectiveConfig={props.perspectiveConfig}
apexChartsConfig={props.apexChartsConfig}
results={groupedResults}
pageType='clientFSResults'
facetUpdateID={props.clientFSState.facetUpdateID}
resultClassConfig={{
createChartData: 'createApexPieChartData',
property: props.clientFSState.groupBy,
title: {
text: props.clientFSState.groupByLabel,
align: 'left'
}
}}
/>
</Route>
<Route path={`${rootUrl}/${perspectiveID}/${searchMode}/download`}>
<CSVButton
results={props.clientFSResults}
layoutConfig={layoutConfig}
portalConfig={portalConfig}
/>
</Route>
</>
)
}
Example #18
Source File: App.jsx From course-plus with Apache License 2.0 | 4 votes |
function App() {
const [filterFormState, setFilterFormState] = useReducer(
(state, newState) => ({ ...state, ...newState }),
{
checkedNj: new Set(),
checkedLx: new Set(),
checkedYx: new Set(),
checkedTy: new Set(),
scheduleKey: '',
lecturerKey: '',
placeKey: '',
keywordType: 'kcmc',
keyword: '',
composition: '',
notes: '',
}
)
const [starLesson, setStarLesson] = useLocalStorageSet(
'starLesson',
new Set([])
)
const [selectedLesson, setSelectedLesson] = useLocalStorageSet(
'selectedLesson',
new Set([])
)
const [sjtuLesson, setSjtuLesson] = useLocalStorageSet(
'sjtuLesson',
new Set([])
)
const [sjtuLessonLoading, setSjtuLessonLoading] = useState(false)
const [loginDialog, setLoginDialog] = useState(false)
const removeStarLesson = (value) => {
const set = new Set(starLesson)
set.delete(value)
setStarLesson(set)
const set2 = new Set(selectedLesson)
set2.delete(value)
setSelectedLesson(set2)
}
const syncFromISJTU = (semester) => {
setSjtuLessonLoading(true)
axios
.get(`/api/course/lesson?term=${semester.replace('_', '-')}`)
.then((resp) => {
if (resp?.data?.error === 'success') {
setSjtuLesson(new Set(resp.data.entities.map((x) => x.code)))
setSjtuLessonLoading(false)
} else {
setSjtuLessonLoading(false)
setLoginDialog(true)
}
})
.catch((e) => {
setLoginDialog(true)
setSjtuLessonLoading(false)
})
}
const handleLogin = (result) => {
if (result) {
window.location.href = '/login?app=course_plus'
}
setLoginDialog(false)
}
const colorize = (starLesson) => {
const colorScale = chroma.scale('Spectral').gamma(0.5)
// const colorScale = chroma.scale(['yellow', 'navy']).mode('lch');
const starLessonArray = [...starLesson]
const result = {}
forEach(
groupBy(starLessonArray, (lesson) =>
lesson.split('-').slice(0, 3).join('-')
),
(v) => {
const colors = colorScale.colors(v.length)
sortedBy(v).forEach((val, idx) => (result[val] = colors[idx]))
}
)
return result
}
return (
<Router>
<LoginModal show={loginDialog} nextStep={handleLogin}></LoginModal>
<div className='container-fluid h-100'>
<div className='row h-100'>
<div className='col-md-3 d-none d-md-block h-100 bg-light overflow-auto'>
<Switch>
<Route exact path='/'>
<Navbar />
</Route>
<Route path='/:semester'>
<Navbar />
</Route>
</Switch>
<div className='container'>
<Switch>
<Route exact path='/'>
<SemesterNav />
</Route>
<Route path='/:semester/:path'>
<SemesterNav />
<hr />
</Route>
</Switch>
<Switch>
<Route path='/:semester/browse'>
<FilterForm
state={filterFormState}
setState={setFilterFormState}
/>
</Route>
<Route path='/:semester/plan'>
<PlanForm
starLesson={starLesson}
removeStarLesson={removeStarLesson}
state={selectedLesson}
setState={setSelectedLesson}
colorMapping={colorize(starLesson)}
/>
</Route>
<Route path='/:semester/classtable'>
<ClassTableForm
sjtuLesson={sjtuLesson}
starLesson={starLesson}
setStarLesson={setStarLesson}
dataLoading={sjtuLessonLoading}
syncFromISJTU={syncFromISJTU}
colorMapping={colorize(sjtuLesson)}
/>
</Route>
</Switch>
<p className='text-muted my-3 small'>
免责声明:本网站课程相关数据来自上海交通大学教学信息服务网。具体开课情况以教务网为准。
</p>
<p className='text-muted my-3 small'>
隐私政策:访问本网站,即代表您同意本网站使用“站长统计”收集您的访问信息。根据相关法律法规,本站不对欧盟用户提供服务。
</p>
<div className='row'>
<div className='col d-flex d-row align-items-center'>
<p className='text-muted my-3 small'>
<a href='https://github.com/SJTU-Plus/course-plus'>
本项目
</a>{' '}
由 <a href='https://plus.sjtu.edu.cn/'>SJTU-Plus</a> 维护。
</p>
</div>
<div className='col-auto m-0 p-0 d-flex d-row align-items-center'>
<GitHubButton
href='https://github.com/sjtu-plus/course-plus'
data-show-count
data-size='large'
>
Star
</GitHubButton>
</div>
</div>
</div>
</div>
<div className='col-md-9 h-100 classtable-wrapper'>
<div className='mb-3'>
<Switch>
<Route path='/:semester/browse'>
<ShowClassTable></ShowClassTable>
</Route>
<Route path='/:semester/plan'>
<ShowClassTable></ShowClassTable>
</Route>
<Route path='/:semester/classtable'>
<SyncButton
syncFromISJTU={syncFromISJTU}
dataLoading={sjtuLessonLoading}
></SyncButton>
</Route>
</Switch>
</div>
<div className='classtable-frame w-100'>
<Switch>
<Route path='/:semester/browse'>
<LessonList
filterData={filterFormState}
state={starLesson}
setState={setStarLesson}
/>
</Route>
<Route path='/:semester/plan'>
<ClassTable
selectedLesson={selectedLesson}
colorMapping={colorize(starLesson)}
/>
</Route>
<Route path='/:semester/classtable'>
<ClassTable
selectedLesson={sjtuLesson}
colorMapping={colorize(sjtuLesson)}
/>
</Route>
</Switch>
</div>
</div>
</div>
</div>
</Router>
)
}
Example #19
Source File: FilterChips.js From edge-frontend with Apache License 2.0 | 4 votes |
FilterChips = ({
filterValues,
setFilterValues,
chipsArray,
setChipsArray,
setPage,
}) => {
const buildChipsArray = () => {
filterValues.forEach((filter) => {
if (filter.type === 'checkbox') {
filter.value.forEach((filterOption) => {
if (
filterOption.isChecked === true &&
!chipsArray.find((chip) => chip.label === filterOption.option)
) {
setChipsArray((prevState) => [
...prevState,
{
label: filterOption.option,
value: filterOption.value || filterOption.option,
apiName: filterOption.optionApiName,
key: filter.label,
},
]);
} else if (
filterOption.isChecked === false &&
chipsArray.find((chip) => chip.label === filterOption.option)
) {
setChipsArray((prevState) => {
const index = prevState.findIndex(
(state) => state.label === filterOption.option
);
return [
...prevState.slice(0, index),
...prevState.slice(index + 1, prevState.length),
];
});
}
});
}
if (filter.type === 'text' && filter.value.length > 0) {
const addTextFilter = { label: filter.value, key: filter.label };
if (chipsArray.find((chip) => chip.key === filter.label)) {
setChipsArray((prevState) =>
prevState.map((f) => {
return f.key === filter.label ? addTextFilter : f;
})
);
} else {
setChipsArray((prevState) => [...prevState, addTextFilter]);
}
} else if (
filter.type === 'text' &&
chipsArray.find((chip) => chip.key === filter.label)
) {
setChipsArray((prevState) => {
const index = prevState.findIndex(
(state) => state.key === filter.label
);
return [
...prevState.slice(0, index),
...prevState.slice(index + 1, prevState.length),
];
});
}
});
};
useEffect(() => {
buildChipsArray();
setPage(1);
}, [filterValues]);
const handleResetFilters = () => {
setFilterValues((prevState) => {
const removedValues = prevState.map((filter) => {
if (filter.type === 'text') {
return { ...filter, value: '' };
}
if (filter.type === 'checkbox') {
const setFalse = filter.value.map((checkbox) => {
checkbox.isChecked = false;
return { ...checkbox, isChecked: false };
});
return { ...filter, value: setFalse };
}
});
return removedValues;
});
setChipsArray([]);
};
const handleDeleteFilter = (filter) => {
const filterLabelIndex = filterValues.findIndex(
(value) => value.label === filter.key
);
setFilterValues((prevState) => {
const changedValue = prevState[filterLabelIndex];
if (changedValue.type === 'text') {
return [
...prevState.slice(0, filterLabelIndex),
{ ...prevState[filterLabelIndex], value: '' },
...prevState.slice(filterLabelIndex + 1, prevState.length),
];
}
if (changedValue.type === 'checkbox') {
const changeFalse = changedValue.value.map((option) =>
option.option === filter.label
? { ...option, isChecked: false }
: option
);
setChipsArray((prevState) => {
const removeIndex = prevState.findIndex((state) => state === filter);
return [
...prevState.slice(0, removeIndex),
...prevState.slice(removeIndex + 1, prevState.length),
];
});
return [
...prevState.slice(0, filterLabelIndex),
{ ...prevState[filterLabelIndex], value: changeFalse },
...prevState.slice(filterLabelIndex + 1, prevState.length),
];
}
return prevState;
});
};
return (
<>
{chipsArray.length > 0
? Object.entries(groupBy(chipsArray, 'key')).map(([key, value]) => (
<ChipGroup
data-testid="filter-chip"
className="pf-u-mr-xs"
categoryName={key}
key={key}
>
{value.map((filter) => (
<Chip onClick={() => handleDeleteFilter(filter)} key={key}>
{filter.label}
</Chip>
))}
</ChipGroup>
))
: null}
{chipsArray.length > 0 ? (
<Button variant="link" onClick={handleResetFilters}>
Clear filters
</Button>
) : null}
</>
);
}
Example #20
Source File: monitoring.updater.js From OctoFarm with GNU Affero General Public License v3.0 | 4 votes |
async function updateGroupState(printers, clientSettings, view) {
const uniqueGroupList = [
...new Set(printers.map((printer) => printer.group)),
];
uniqueGroupList.forEach((group) => {
const cleanGroup = encodeURIComponent(group);
const filteredGroupPrinterList = printers.filter((printer) => {
if (encodeURIComponent(printer.group) === cleanGroup){
return printer;
}
});
checkGroupQuickConnectState(filteredGroupPrinterList, cleanGroup);
})
printers.forEach((printer, index) => {
if (printer.group !== "" || !printer.disabled) {
const elements = grabElements(printer);
if (!elements?.row) return;
elements.row.style.order = index;
if (printer.display) {
if (elements.row.style.display === "none") {
switch (view) {
case "list":
elements.row.style.display = "table";
break;
case "panel":
elements.row.style.display = "block";
break;
case "camera":
elements.row.style.display = "block";
break;
case "group":
elements.row.style.display = "flex";
break;
case "combined":
elements.row.style.display = "flex";
break;
}
}
} else {
if (elements.row.style.display !== "none") {
elements.row.style.display = "none";
}
return;
}
let hideOffline = "";
let hideClosed = "";
if (!clientSettings?.views?.showDisconnected) {
hideClosed = "hidden";
}
if (!clientSettings?.views?.showOffline) {
hideOffline = "hidden";
}
if (printer.printerState.colour.category === "Active") {
// Set the state
if (elements.row.classList.contains(hideClosed)) {
elements.row.classList.remove(hideClosed);
}
if (elements.row.classList.contains(hideOffline)) {
elements.row.classList.remove(hideOffline);
}
} else if (
printer.printerState.colour.category === "Idle" ||
printer.printerState.colour.category === "Complete"
) {
if (elements.row.classList.contains(hideClosed)) {
elements.row.classList.remove(hideClosed);
}
if (elements.row.classList.contains(hideOffline)) {
elements.row.classList.remove(hideOffline);
}
} else if (printer.printerState.state === "Disconnected") {
if (hideClosed !== "") {
elements.row.classList.add(hideClosed);
}
} else if (printer.printerState.colour.category === "Offline") {
if (hideOffline !== "") {
elements.row.classList.add(hideOffline);
}
}
UI.doesElementNeedUpdating(
printer.printerName,
elements.name,
"innerHTML"
);
UI.doesElementNeedUpdating(
printer.printerState.state,
elements.state,
"innerHTML"
);
UI.doesElementNeedUpdating(
`w-100 badge ${printer.printerState.colour.category}`,
elements.state,
"classList"
);
}
});
const groupedPrinters = mapValues(groupBy(printers, "group"));
for (const key in groupedPrinters) {
if (groupedPrinters.hasOwnProperty(key)) {
if (key !== "") {
const currentGroupEncoded = encodeURIComponent(key);
const elements = grabGroupElements(currentGroupEncoded);
const offlinePrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.colour.category === "Offline"
).length;
const disconnectedPrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.state === "Disconnected"
).length;
const idlePrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.colour.category === "Idle"
).length;
const completePrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.colour.category === "Complete"
).length;
const activePrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.colour.category === "Active"
).length;
const pausedPrinters = groupedPrinters[key].filter(
(obj) => obj.printerState.state === "Paused"
).length;
const pausingPrinters = groupedPrinters[key].filter(
(obj) =>
obj.printerState.state === "Pausing" ||
obj.printerState.state === "Cancelling"
).length;
const filesSelected = groupedPrinters[key].filter(
(obj) => obj?.currentJob?.fileName !== "No File Selected"
).length;
let combinedProgress = groupedPrinters[key].reduce(function (a, b) {
return a + b?.["currentJob"]?.["progress"];
}, 0);
const actualProgress = combinedProgress / groupedPrinters[key].length;
UI.doesElementNeedUpdating(
actualProgress.toFixed(0) + "%",
elements.progress,
"innerHTML"
);
elements.progress.style.width = actualProgress + "%";
if (actualProgress < 100) {
UI.doesElementNeedUpdating(
"progress-bar progress-bar-striped bg-warning",
elements.progress,
"classList"
);
} else if (actualProgress === 100) {
UI.doesElementNeedUpdating(
"progress-bar progress-bar-striped bg-success",
elements.progress,
"classList"
);
}
if (activePrinters === groupedPrinters[key].length) {
//Set the buttons
if (elements.start) {
elements.start.disabled = true;
}
if (elements.stop) {
elements.stop.disabled = false;
}
if (pausingPrinters === groupedPrinters[key].length) {
if (elements.start) {
elements.start.classList.remove("hidden");
}
if (elements.stop) {
elements.stop.disabled = false;
}
if (elements.resume) {
elements.resume.classList.add("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.remove("hidden");
}
if (elements.restart) {
elements.restart.disabled = true;
elements.restart.classList.add("hidden");
}
} else if (pausedPrinters === groupedPrinters[key].length) {
if (elements.start) {
elements.start.classList.add("hidden");
}
if (elements.resume) {
elements.resume.disabled = false;
elements.resume.classList.remove("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.add("hidden");
}
if (elements.restart) {
elements.restart.disabled = false;
elements.restart.classList.remove("hidden");
}
} else {
if (elements.start) {
elements.start.classList.remove("hidden");
}
if (elements.resume) {
elements.resume.disabled = true;
elements.resume.classList.add("hidden");
}
if (elements.pause) {
elements.pause.disabled = false;
elements.pause.classList.remove("hidden");
}
if (elements.restart) {
elements.restart.disabled = true;
elements.restart.classList.add("hidden");
}
}
} else if (
idlePrinters === groupedPrinters[key].length ||
completePrinters === groupedPrinters[key].length
) {
if (filesSelected === groupedPrinters[key].length) {
if (elements.start) {
elements.start.disabled = false;
}
if (elements.stop) {
elements.stop.disabled = true;
}
if (elements.resume) {
elements.resume.disabled = true;
}
if (elements.pause) {
elements.pause.disabled = true;
}
if (elements.restart) {
elements.restart.disabled = true;
}
} else {
if (elements.start) {
elements.start.disabled = true;
}
if (elements.stop) {
elements.stop.disabled = true;
}
if (elements.resume) {
elements.resume.disabled = true;
}
if (elements.pause) {
elements.pause.disabled = true;
}
if (elements.restart) {
elements.restart.disabled = true;
}
}
if (pausedPrinters === groupedPrinters[key].length) {
if (elements.start) {
elements.start.classList.add("hidden");
}
if (elements.stop) {
elements.stop.disabled = false;
}
if (elements.resume) {
elements.resume.disabled = false;
elements.resume.classList.remove("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.add("hidden");
}
if (elements.restart) {
elements.restart.disabled = false;
elements.restart.classList.remove("hidden");
}
} else {
if (elements.start) {
elements.start.classList.remove("hidden");
}
if (elements.resume) {
elements.resume.disabled = true;
elements.resume.classList.add("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.remove("hidden");
}
if (elements.restart) {
elements.restart.disabled = true;
elements.restart.classList.add("hidden");
}
}
} else if (disconnectedPrinters === groupedPrinters[key].length) {
if (elements.start) {
elements.start.disabled = true;
elements.start.classList.remove("hidden");
}
if (elements.stop) {
elements.stop.disabled = true;
}
if (elements.resume) {
elements.resume.disabled = true;
elements.resume.classList.add("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.remove("hidden");
}
if (elements.restart) {
elements.restart.disabled = true;
elements.restart.classList.add("hidden");
}
} else if (offlinePrinters === groupedPrinters[key].length) {
if (elements.start) {
elements.start.disabled = true;
elements.start.classList.remove("hidden");
}
if (elements.stop) {
elements.stop.disabled = true;
}
if (elements.resume) {
elements.resume.disabled = true;
elements.resume.classList.add("hidden");
}
if (elements.pause) {
elements.pause.disabled = true;
elements.pause.classList.remove("hidden");
}
if (elements.restart) {
elements.restart.disabled = true;
elements.restart.classList.add("hidden");
}
}
}
}
}
}
Example #21
Source File: monitoring.updater.js From OctoFarm with GNU Affero General Public License v3.0 | 4 votes |
function addGroupListeners(printers) {
const groupedPrinters = mapValues(groupBy(printers, "group"));
for (const key in groupedPrinters) {
if (groupedPrinters.hasOwnProperty(key)) {
const currentGroupEncoded = encodeURIComponent(key);
//Play button listeners
let playBtn = document.getElementById("play-" + currentGroupEncoded);
if (playBtn) {
playBtn.addEventListener("click", async (e) => {
e.target.disabled = true;
for (const printer of groupedPrinters[key]) {
const opts = {
command: "start",
};
const print = returnPrinterInfo(printer._id);
const { status } = await OctoPrintClient.jobAction(print, opts, e);
printActionStatusResponse(status, "print");
}
});
}
let cancelBtn = document.getElementById("cancel-" + currentGroupEncoded);
if (cancelBtn) {
cancelBtn.addEventListener("click", (e) => {
bootbox.confirm({
message: "Are you sure you want to cancel the ongoing prints?",
buttons: {
cancel: {
label: "<i class=\"fa fa-times\"></i> Cancel",
},
confirm: {
label: "<i class=\"fa fa-check\"></i> Confirm",
},
},
async callback(result) {
if (result) {
e.target.disabled = true;
for (const printer of groupedPrinters[key]) {
const print = returnPrinterInfo(printer._id);
const opts = {
command: "cancel",
};
const { status } = await OctoPrintClient.jobAction(
print,
opts,
e
);
printActionStatusResponse(status, "cancel");
}
}
},
});
});
}
let restartBtn = document.getElementById(
"restart-" + currentGroupEncoded
);
if (restartBtn) {
restartBtn.addEventListener("click", async (e) => {
e.target.disabled = true;
for (const printer of groupedPrinters[key]) {
const opts = {
command: "restart",
};
const print = returnPrinterInfo(printer._id);
const { status } = await OctoPrintClient.jobAction(print, opts, e);
printActionStatusResponse(status, "restart");
}
});
}
let pauseBtn = document.getElementById("pause-" + currentGroupEncoded);
if (pauseBtn) {
pauseBtn.addEventListener("click", async (e) => {
e.target.disabled = true;
for (const printer of groupedPrinters[key]) {
const opts = {
command: "pause",
action: "pause",
};
const print = returnPrinterInfo(printer._id);
const { status } = await OctoPrintClient.jobAction(print, opts, e);
printActionStatusResponse(status, "pause");
}
});
}
let resumeBtn = document.getElementById("resume-" + currentGroupEncoded);
if (resumeBtn) {
resumeBtn.addEventListener("click", async (e) => {
e.target.disabled = true;
for (const printer of groupedPrinters[key]) {
const opts = {
command: "pause",
action: "resume",
};
const print = returnPrinterInfo(printer._id);
const { status } = await OctoPrintClient.jobAction(print, opts, e);
printActionStatusResponse(status, "resume");
}
});
}
let filesBtn = document.getElementById(
"unifiedFiles-" + currentGroupEncoded
);
if (filesBtn) {
filesBtn.addEventListener("click", async () => {
const idList = [];
for (const printer of groupedPrinters[key]) {
idList.push(printer._id);
}
const fileList = await OctoFarmClient.get(
"printers/listUnifiedFiles/" + JSON.stringify(idList)
);
drawGroupFiles(fileList);
});
}
}
}
return "done";
}