diff --git a/app/herdbook.py b/app/herdbook.py index e3750d83..7d7ea733 100644 --- a/app/herdbook.py +++ b/app/herdbook.py @@ -907,7 +907,7 @@ def get_kinship(g_id): response = requests.get( "http://{}:{}/kinship/{}".format(settings.rapi.host, settings.rapi.port, g_id), params={"update_data": "TRUE"}, - timeout=30, + timeout=60, ) if response.status_code == 200: diff --git a/frontend/public/android-chrome-192x192.png b/frontend/public/android-chrome-192x192.png new file mode 100644 index 00000000..ec3f6c34 Binary files /dev/null and b/frontend/public/android-chrome-192x192.png differ diff --git a/frontend/public/android-chrome-512x512.png b/frontend/public/android-chrome-512x512.png new file mode 100644 index 00000000..c1e87368 Binary files /dev/null and b/frontend/public/android-chrome-512x512.png differ diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png new file mode 100644 index 00000000..0196ad1f Binary files /dev/null and b/frontend/public/apple-touch-icon.png differ diff --git a/frontend/public/favicon-16x16.png b/frontend/public/favicon-16x16.png new file mode 100644 index 00000000..3b263529 Binary files /dev/null and b/frontend/public/favicon-16x16.png differ diff --git a/frontend/public/favicon-32x32.png b/frontend/public/favicon-32x32.png new file mode 100644 index 00000000..07895c25 Binary files /dev/null and b/frontend/public/favicon-32x32.png differ diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 00000000..f285b31d Binary files /dev/null and b/frontend/public/favicon.ico differ diff --git a/frontend/public/index.html b/frontend/public/index.html index b5238539..c32896c0 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -1,14 +1,33 @@ - - - - - - Stamboken Online - - - -
- - + + + + + + + + + + + + + + + + + Stamboken Online + + +
+ + diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json new file mode 100644 index 00000000..fbfa70ea --- /dev/null +++ b/frontend/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "Stamboken", + "name": "Stamboken Online", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#1976d2", + "background_color": "#ffffff" +} diff --git a/frontend/public/mstile-150x150.png b/frontend/public/mstile-150x150.png new file mode 100644 index 00000000..3ca30623 Binary files /dev/null and b/frontend/public/mstile-150x150.png differ diff --git a/frontend/public/safari-pinned-tab.svg b/frontend/public/safari-pinned-tab.svg new file mode 100644 index 00000000..a3f20c9f --- /dev/null +++ b/frontend/public/safari-pinned-tab.svg @@ -0,0 +1,114 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + + diff --git a/frontend/src/SelectHerdStep.tsx b/frontend/src/SelectHerdStep.tsx index 7974cb41..af0b0fcb 100644 --- a/frontend/src/SelectHerdStep.tsx +++ b/frontend/src/SelectHerdStep.tsx @@ -1,6 +1,6 @@ // File: SelectHerdStep.tsx -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useCallback, useMemo } from "react"; import { Button, Typography, @@ -11,10 +11,13 @@ import { } from "@material-ui/core"; import { Edit as EditIcon } from "@material-ui/icons"; import { BreedingForm } from "./breeding_form"; +import { useBreedingContext } from "./breeding_context"; import { useDataContext } from "@app/data_context"; import { useMessageContext } from "@app/message_context"; import { useUserContext } from "@app/user_context"; import { get } from "@app/communication"; +import { ExtendedBreeding, Breeding } from "./data_context_global"; +import { VariantType } from "notistack"; interface SelectHerdStepProps { user: any; @@ -27,6 +30,20 @@ interface SelectHerdStepProps { onUpdateStatus?: (status: string) => void; } +interface RawBreeding { + id: number; + birth_date?: string; + breed_date?: string; + mother?: string; + mother_name?: string; + father?: string; + father_name?: string; + individuals?: any[]; + litter_size?: number; + litter_size6w?: number; + breeding_herd: string; +} + export const SelectHerdStep: React.FC = ({ user, genebankName, @@ -40,10 +57,14 @@ export const SelectHerdStep: React.FC = ({ const { genebanks } = useDataContext(); const [herdOptions, setHerdOptions] = useState([]); const [searchTerm, setSearchTerm] = useState(""); - const [selectedHerdBreedings, setSelectedHerdBreedings] = useState([]); + const [herdBreedings, setHerdBreedings] = useState([]); const { userMessage } = useMessageContext(); - const [selectedBreeding, setSelectedBreeding] = useState(null); + const [selectedBreeding, setSelectedBreeding] = useState< + ExtendedBreeding | "new" | null + >(null); const [isBreedingDialogOpen, setIsBreedingDialogOpen] = useState(false); + const breedingContext = useBreedingContext(); + const [isLoading, setIsLoading] = useState(false); // Initialize herd options based on genebankName and user ownership useEffect(() => { @@ -53,194 +74,169 @@ export const SelectHerdStep: React.FC = ({ setHerdOptions(foundGenebank.herds); } } else if (user?.is_owner && user.is_owner.length > 0) { - setHerdOptions( - genebanks.flatMap((g: any) => - g.herds.filter((herd: any) => user.is_owner.includes(herd.herd)) - ) + const filteredHerds = genebanks.flatMap((g: any) => + g.herds.filter((herd: any) => user.is_owner.includes(herd.herd)) ); + setHerdOptions(filteredHerds); } }, [genebankName, genebanks, user]); - // Automatically set herdId if user owns only one herd and specific conditions are met - useEffect(() => { - if ( - !genebankName && - user?.is_owner && - user.is_owner.length === 1 && - !user.is_admin && - (!user.is_manager || user.is_manager.length === 0) - ) { - handleHerdSelect(user.is_owner[0]); - } - }, [genebankName, user]); + // Fetch breedings function + const fetchBreedings = useCallback(async () => { + if (!herdId || isLoading) return; - const handleHerdSelect = (id: string) => { - setHerdId(id); - // onUpdateStatus will be called after breeding data is loaded - }; + setIsLoading(true); + try { + const data = (await get(`/api/breeding/${herdId}`)) as { + breedings: RawBreeding[]; + }; - const filterBreedingsForYear = (breedings: any[], year: number) => { - const filtered = breedings.filter((breeding) => { - // If we have a birth_date in the report year, include it - if (breeding.birth_date) { - const birthYear = new Date(breeding.birth_date).getFullYear(); - if (birthYear === year) { - return true; - } + if (!data?.breedings) { + setHerdBreedings([]); + return; } - // Check breed_date regardless of whether we have a birth_date - if (breeding.breed_date) { - const breedDate = new Date(breeding.breed_date); - const breedYear = breedDate.getFullYear(); - - if (breedYear === year) { - // Exclude if it's in the last 30 days of the year - const yearEnd = new Date(year, 11, 31); // December 31st - const daysBefore = Math.floor( - (yearEnd.getTime() - breedDate.getTime()) / (1000 * 60 * 60 * 24) - ); - return daysBefore >= 30; + // Sort breedings by birth_date ascending, then by id ascending + const sortedBreedings = data.breedings.sort( + (a: RawBreeding, b: RawBreeding) => { + const dateA = new Date(a.birth_date || "9999-12-31"); + const dateB = new Date(b.birth_date || "9999-12-31"); + if (dateA < dateB) return -1; + if (dateA > dateB) return 1; + return a.id - b.id; } - } + ); - return false; - }); + // Add numbering and ensure all properties are present + const processedBreedings: ExtendedBreeding[] = sortedBreedings.map( + (breeding: RawBreeding, index: number) => ({ + ...breeding, + number: index + 1, + mother_name: breeding.mother_name || breeding.mother || "", + father_name: breeding.father_name || breeding.father || "", + individuals: breeding.individuals || [], + breed_notes: "", + birth_notes: "", + birth_date: breeding.birth_date || null, + breed_date: breeding.breed_date || null, + mother: breeding.mother || "", + father: breeding.father || "", + litter_size: breeding.litter_size || null, + litter_size6w: breeding.litter_size6w || null, + breeding_herd: breeding.breeding_herd, + }) + ); - return filtered; - }; + setHerdBreedings(processedBreedings); + onUpdateStatus?.("completed"); + } catch (error: unknown) { + userMessage("Kunde inte hämta kullar.", "error"); + console.error("Failed to fetch breedings:", error); + onUpdateStatus?.("error"); + } finally { + setIsLoading(false); + } + }, [herdId, isLoading, onUpdateStatus, userMessage]); + // Fetch breedings when herdId changes useEffect(() => { - if (herdId) { - get(`/api/breeding/${herdId}`).then( - (data: { breedings: any[] }) => { - if (data && data.breedings) { - // Sort breedings by birth_date ascending, then by id ascending - const sortedBreedings = data.breedings.sort((a, b) => { - // First compare by birth_date - const dateA = new Date(a.birth_date || "9999-12-31"); - const dateB = new Date(b.birth_date || "9999-12-31"); - if (dateA < dateB) return -1; - if (dateA > dateB) return 1; - // If dates are equal, compare by id - return a.id - b.id; - }); - // Add numbering and ensure all properties are present - const numberedBreedings = sortedBreedings.map( - (breeding, index) => ({ - ...breeding, - number: index + 1, - mother_name: breeding.mother_name || breeding.mother || "", - father_name: breeding.father_name || breeding.father || "", - individuals: breeding.individuals || [], - }) - ); - - let filteredBreedings = numberedBreedings; - if (reportYear) { - filteredBreedings = filterBreedingsForYear( - numberedBreedings, - reportYear - ); - // Renumber the filtered breedings - filteredBreedings = filteredBreedings.map((breeding, index) => ({ - ...breeding, - number: index + 1, - })); - } - setSelectedHerdBreedings(filteredBreedings); - // Mark step as completed only after breeding data is loaded - onUpdateStatus?.("completed"); - } - }, - (error) => { - userMessage("Kunde inte hämta kullar.", "error"); - console.error("Failed to fetch breedings:", error); - onUpdateStatus?.("error"); - } - ); - } else { - setSelectedHerdBreedings([]); + if (!herdId) { + setHerdBreedings([]); + onUpdateStatus?.("error"); + return; } - }, [herdId, reportYear, userMessage, onUpdateStatus]); - - const handleBreedingsChanged = () => { - // Refresh the breedings data - if (herdId) { - get(`/api/breeding/${herdId}`).then((data: { breedings: any[] }) => { - if (data && data.breedings) { - const sortedBreedings = data.breedings.sort((a, b) => { - const dateA = new Date(a.birth_date || "9999-12-31"); - const dateB = new Date(b.birth_date || "9999-12-31"); - if (dateA < dateB) return -1; - if (dateA > dateB) return 1; - return a.id - b.id; - }); - const numberedBreedings = sortedBreedings.map((breeding, index) => ({ - ...breeding, - number: index + 1, - mother_name: breeding.mother_name || breeding.mother || "", - father_name: breeding.father_name || breeding.father || "", - individuals: breeding.individuals || [], - })); - - let filteredBreedings = numberedBreedings; - if (reportYear) { - filteredBreedings = filterBreedingsForYear( - numberedBreedings, - reportYear - ); - filteredBreedings = filteredBreedings.map((breeding, index) => ({ - ...breeding, - number: index + 1, - })); - } - setSelectedHerdBreedings(filteredBreedings); - } - }); - } - }; - const handleBreedingClick = (breeding: any) => { + fetchBreedings(); + }, [herdId]); + + const handleHerdSelect = useCallback( + (id: string) => { + setHerdId(id); + }, + [setHerdId] + ); + + const handleBreedingClick = useCallback((breeding: ExtendedBreeding) => { setSelectedBreeding(breeding); setIsBreedingDialogOpen(true); - }; + }, []); - const handleNewBreedingClick = () => { + const handleNewBreedingClick = useCallback(() => { setSelectedBreeding("new"); setIsBreedingDialogOpen(true); - }; + }, []); - const handleBreedingDialogClose = () => { + const handleBreedingDialogClose = useCallback(() => { setSelectedBreeding(null); setIsBreedingDialogOpen(false); - }; + fetchBreedings(); + }, [fetchBreedings]); + + // Get filtered breedings for the report year + const selectedHerdBreedings = useMemo(() => { + if (!herdBreedings?.length || !reportYear) return herdBreedings || []; + + return herdBreedings + .filter((breeding) => { + if (!breeding) return false; + + // If we have a birth_date in the report year, include it + if (breeding.birth_date) { + const birthYear = new Date(breeding.birth_date).getFullYear(); + if (birthYear === reportYear) { + return true; + } + } + + // Check breed_date regardless of whether we have a birth_date + if (breeding.breed_date) { + const breedDate = new Date(breeding.breed_date); + const breedYear = breedDate.getFullYear(); + + if (breedYear === reportYear) { + // Exclude if it's in the last 30 days of the year + const yearEnd = new Date(reportYear, 11, 31); + const daysBefore = Math.floor( + (yearEnd.getTime() - breedDate.getTime()) / (1000 * 60 * 60 * 24) + ); + return daysBefore >= 30; + } + } + + return false; + }) + .map((breeding, index) => ({ + ...breeding, + number: index + 1, + })); + }, [herdBreedings, reportYear]); + + // Filter herds based on search term + const filteredHerds = useMemo(() => { + if (!searchTerm) return herdOptions; + const search = searchTerm.toLowerCase(); + return herdOptions.filter((herd) => { + const herdName = herd.herd_name?.toLowerCase() || ""; + const herdIdLower = herd.herd?.toLowerCase() || ""; + return herdName.includes(search) || herdIdLower.includes(search); + }); + }, [herdOptions, searchTerm]); // Helper function to determine if a row should be highlighted - const getRowStyle = (breeding: any) => { - // Red background for missing birth date or missing litter size at 6 weeks + const getRowStyle = useCallback((breeding: any) => { if (!breeding.birth_date || breeding.litter_size6w == null) { - return { backgroundColor: "#ffebee" }; // Light red background + return { backgroundColor: "#ffebee" }; } - // Yellow background when litter size at 6 weeks is 0 (for verification) if (breeding.litter_size6w === 0) { - return { backgroundColor: "#fff3e0" }; // Light yellow background + return { backgroundColor: "#fff3e0" }; } return {}; - }; + }, []); if (!genebankName && (!user?.is_owner || user.is_owner.length === 0)) { return Du äger ingen besättning.; } - // Define filteredHerds before return - const filteredHerds = herdOptions.filter((herd: any) => { - const herdName = herd.herd_name ? herd.herd_name.toLowerCase() : ""; - const herdIdLower = herd.herd ? herd.herd.toLowerCase() : ""; - const search = searchTerm.toLowerCase(); - return herdName.includes(search) || herdIdLower.includes(search); - }); - // Helper function to render the info card const renderInfoCard = (selectedHerdId: string) => (
= ({ { - handleBreedingsChanged(); - handleBreedingDialogClose(); + handleBreedingsChanged={(shouldClose?: boolean) => { + // Refresh the data first + fetchBreedings(); + // Close if explicitly told to do so by the form + if (shouldClose) { + handleBreedingDialogClose(); + } }} handleActive={() => {}} /> diff --git a/frontend/src/breeding_form.tsx b/frontend/src/breeding_form.tsx index 08c4c7df..990ca28b 100644 --- a/frontend/src/breeding_form.tsx +++ b/frontend/src/breeding_form.tsx @@ -70,7 +70,7 @@ export function BreedingForm({ }: { data: Breeding | "new"; herdId: string | undefined; - handleBreedingsChanged: () => void; + handleBreedingsChanged: (shouldClose?: boolean) => void; handleActive: (breeding: Breeding) => void; }) { const { @@ -496,7 +496,8 @@ export function BreedingForm({ if (breeding.birth_date === null) { userMessage("Kullen har sparats.", "success"); - + await setHerdChangeListener(herdChangeListener + 1); + handleBreedingsChanged(); return; } @@ -520,7 +521,7 @@ export function BreedingForm({ ); } await setHerdChangeListener(herdChangeListener + 1); - handleBreedingsChanged(); + handleBreedingsChanged(true); } break; case 1: @@ -529,13 +530,13 @@ export function BreedingForm({ breeding.mother = breedingMatch.mother; await handleEditableBreedingUpdates(breeding, breedingMatch); await setHerdChangeListener(herdChangeListener + 1); - handleBreedingsChanged(); + handleBreedingsChanged(!!breeding.birth_date); break; default: // update breeding event await handleEditableBreedingUpdates(breeding, breedingMatch); await setHerdChangeListener(herdChangeListener + 1); - handleBreedingsChanged(); + handleBreedingsChanged(!!breeding.birth_date); break; } }; diff --git a/frontend/src/filter_table.tsx b/frontend/src/filter_table.tsx index 6ee4e13a..7779883f 100644 --- a/frontend/src/filter_table.tsx +++ b/frontend/src/filter_table.tsx @@ -486,6 +486,7 @@ export function FilterTable({ <> {currentFilters.map((filter) => ( @@ -494,11 +495,11 @@ export function FilterTable({ } > ) => { if ( @@ -542,7 +543,9 @@ export function FilterTable({ > - {action && {actionLabel}} + {action && ( + {actionLabel} + )} {visibleColumns.map((column) => ( {sortedIndividuals .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((row, index) => { + .map((row) => { return ( {action && ( action && action(event, row)} > @@ -586,7 +590,7 @@ export function FilterTable({ {visibleColumns.map((column) => { return ( {column.render diff --git a/frontend/src/static_pages.tsx b/frontend/src/static_pages.tsx index e717af9f..e6abccb2 100644 --- a/frontend/src/static_pages.tsx +++ b/frontend/src/static_pages.tsx @@ -16,23 +16,21 @@ export function About() { Välkommen till Stamboken Online -

- Detta är Föreningen Gotlandskaninens system för stambokföring online. - Använd menyn för att logga in med hjälp av ditt Gottiskonto. Har du - inget sådant kan du som är medlem i föreningen ansöka om ett via detta - formulär.{" "} - - Kontoansökan - -

-

- Behöver du hjälp kontakt admin@gotlandskanin.se, du kommer också åt - hjälpsidorna under menyval "Hjälp" när du väl har loggat in. -

+ Detta är Föreningen Gotlandskaninens system för stambokföring online. + Använd menyn för att logga in med hjälp av ditt Gottiskonto. Har du + inget sådant kan du som är medlem i föreningen ansöka om ett via detta + formulär.{" "} + + Kontoansökan + +
+ + Behöver du hjälp kontakt admin@gotlandskanin.se, du kommer också åt + hjälpsidorna under menyval "Hjälp" när du väl har loggat in.
); @@ -45,25 +43,23 @@ export function HelpStamboken() { Stamboken Online -

- En användarmanual är påbörjad men den är - inte komplett: - - Användarmanual för Stamboken Online - - Bidra gärna med ändringar till dokumentet eller lägg - till kommentarer osv.{" "} -

-

-

- Som ett komplement till den oskrivna manualen finns följande - presentationsserie : -

-

+ En användarmanual är påbörjad men den är inte + komplett: + + Användarmanual för Stamboken Online + + Bidra gärna med ändringar till dokumentet eller lägg till + kommentarer osv.{" "} +
+ + Som ett komplement till den oskrivna manualen finns följande + presentationsserie : + + -

-

- Om något fortfarande är oklart finns det flera sätt - att få hjälp : -

-

-
    -
  1. - Posta en fråga i forumet. Tex i   - - Tråden om Stamboken online - - . -
  2. -
  3. - Du kan också använda feedback funktionen direkt på - sidan, den är väldigt bra om du stöter på en - tex bugg. Då klickar du på den röda rutan till - höger där det står "Ge oss feedback". -
  4. + + + Om något fortfarande är oklart finns det flera sätt att + få hjälp : + +
      +
    1. + Posta en fråga i forumet. Tex i   + + Tråden om Stamboken online + + . +
    2. +
    3. + Du kan också använda feedback funktionen direkt på + sidan, den är väldigt bra om du stöter på en tex + bugg. Då klickar du på den röda rutan till höger + där det står "Ge oss feedback". +
    4. +
    5. + Använd vårt{" "} + + chatrum + +  . +
    6. +
    7. + Sänd  E-post till{" "} + + admin@gotlandskaninen.se + + . +
    8. +
    9. + Behöver du hjälp med redigering  av någon kanin + så kontaktar du Genbanksansvariga direkt.{" "} +
    10. + + - - -
    11. Kontakta valfri person i styrelsen,
    12. -
    - +
  5. Kontakta valfri person i styrelsen,
  6. +
); } @@ -188,47 +182,45 @@ export function Gotlandskaninen() { Gotlandskaninen
-

- Gotlandskaninen är en rest av den gamla svenska lantraskaninen. På - 1970-talet uppmärksammades att det fanns några gårdar på Gotland som - hade kvar kaniner av den gamla stammen. De gavs då namnet - Gotlandskanin. Efter en inventering 1993 slöts rasregistret och dagens - Gotlandskaniner är ättlingar till inventeringsdjuren. -

-

- En fullvuxen Gotlandskanin väger 3-4 kg. Öronen är upprättstående och - pälsen kort. Färg och teckning varierar mycket, och de flesta typer - som förekommer bland raskaniner återfinns hos gotlänningen, men oftast - i mindre utpräglad form. -

-

- Till temperamentet är Gotlandskaninen livlig och nyfiken och visar - ofta stort intresse för sin omgivning. Normalt får Gotlandskaninen 6-8 - ungar per kull. Ungarna tillväxer relativt långsamt i jämförelse med - utpräglade produktionsraser. Men å andra sidan är man normalt - återhållsam med kraftfoder till Gotlandskaniner. Basfödan är hö, eller - på sommarhalvåret, gräs och örter. -

-

- Bevarandearbetet organiseras av Föreningen Gotlandskaninen i ett - genbankssystem. Aveln sker i speciella besättningar som föreningen - godkänt. Det finns ungefär 150 sådana besättningar spridda över hela - Sverige för Gotlandskanin. De rapporterar till föreningen vad som sker - i besättningen och utfärdar stamtavlor (genbanksintyg) för de djur som - går vidare i avelsarbetet i gamla eller nya besättningar. -

-

- Om du är intresserad av att veta mer, eller vill starta en - genbanksbesättning för Gotlandskanin, kontakta genbanksansvarig, - - gotlandskanin@gotlandskaninen.se - - . -

+ Gotlandskaninen är en rest av den gamla svenska lantraskaninen. På + 1970-talet uppmärksammades att det fanns några gårdar på Gotland som + hade kvar kaniner av den gamla stammen. De gavs då namnet Gotlandskanin. + Efter en inventering 1993 slöts rasregistret och dagens Gotlandskaniner + är ättlingar till inventeringsdjuren. +
+ + En fullvuxen Gotlandskanin väger 3-4 kg. Öronen är upprättstående och + pälsen kort. Färg och teckning varierar mycket, och de flesta typer som + förekommer bland raskaniner återfinns hos gotlänningen, men oftast i + mindre utpräglad form. + + + Till temperamentet är Gotlandskaninen livlig och nyfiken och visar ofta + stort intresse för sin omgivning. Normalt får Gotlandskaninen 6-8 ungar + per kull. Ungarna tillväxer relativt långsamt i jämförelse med + utpräglade produktionsraser. Men å andra sidan är man normalt + återhållsam med kraftfoder till Gotlandskaniner. Basfödan är hö, eller + på sommarhalvåret, gräs och örter. + + + Bevarandearbetet organiseras av Föreningen Gotlandskaninen i ett + genbankssystem. Aveln sker i speciella besättningar som föreningen + godkänt. Det finns ungefär 150 sådana besättningar spridda över hela + Sverige för Gotlandskanin. De rapporterar till föreningen vad som sker i + besättningen och utfärdar stamtavlor (genbanksintyg) för de djur som går + vidare i avelsarbetet i gamla eller nya besättningar. + + + Om du är intresserad av att veta mer, eller vill starta en + genbanksbesättning för Gotlandskanin, kontakta genbanksansvarig,{" "} + + gotlandskanin@gotlandskaninen.se + + . ); @@ -241,52 +233,50 @@ export function Mellerudskaninen() { Mellerudskaninen -

- Mellerudskaninen är en rest av den gamla svenska lantraskaninen. Den - fanns i en besättning hos Edith Johansson, som bodde nära Mellerud i - Dalsland. Kaninerna gavs därför namnet Mellerudskanin. -

-

- Kaninerna liknar mycket Gotlandskaninen i kroppsbyggnaden, men finns - bara som brokigt svartvita (holländarteckning) eller som helvita - (albino). Vuxna djur väger runt 3 kg, har kort päls och upprättstående - öron. Normalt får Mellerudskaninerna 4-6 ungar. Mellerudskaninen - uppfattas ofta som något lugnare än Gotlandskaninen. -

-

- I oktober 2001 gjordes ett första besök hos ”Edith i Sjöskogen” sedan - Föreningen Gotlandskaninen blivit uppmärksammad på att den dövstumma - äldre damen höll en intressant grupp kaniner av äldre härstamning. - Djuren har sedan 1937 funnits i Mellerud då Ediths familj flyttade dit - från Stora Grimön i Vänern. Den enda kända inkorsningen av djur - utifrån är från 1968. Då togs två svart-vit brokiga djur, en hona och - en hane, in i besättningen. Djurantalet i har tidigare legat kring - 15-20 men minskade under de sista åren drastiskt. De sista djuren - köptes ut från ursprungsbesättningen under 2007. -

-

- I slutet av oktober 2011 godkände Jordbruksverket Föreningen - Gotlandskaninens avelsplan för Mellerudskanin och därmed är - Mellerudskaninen officiellt en svensk husdjursras. Bevarandearbete - organiseras av Föreningen Gotlandskaninen i ett genbankssystem. Aveln - sker i speciella besättningar som föreningen godkänt. Det finns - ungefär 50 sådana besättningar för Mellerudskanin spridda över hela - Sverige. De rapporterar till föreningen vad som sker i besättningen - och utfärdar stamtavlor (genbanksintyg) för de djur som går vidare i - avelsarbetet i gamla eller nya besättningar. -

-

- Om du är intresserad av att veta mer, eller vill starta en - genbanksbesättning för Mellerudskanin, kontakta genbanksansvarig, - - mellerudskanin@gotlandskaninen.se - - . -

+ Mellerudskaninen är en rest av den gamla svenska lantraskaninen. Den + fanns i en besättning hos Edith Johansson, som bodde nära Mellerud i + Dalsland. Kaninerna gavs därför namnet Mellerudskanin. +
+ + Kaninerna liknar mycket Gotlandskaninen i kroppsbyggnaden, men finns + bara som brokigt svartvita (holländarteckning) eller som helvita + (albino). Vuxna djur väger runt 3 kg, har kort päls och upprättstående + öron. Normalt får Mellerudskaninerna 4-6 ungar. Mellerudskaninen + uppfattas ofta som något lugnare än Gotlandskaninen. + + + I oktober 2001 gjordes ett första besök hos "Edith i Sjöskogen" sedan + Föreningen Gotlandskaninen blivit uppmärksammad på att den dövstumma + äldre damen höll en intressant grupp kaniner av äldre härstamning. + Djuren har sedan 1937 funnits i Mellerud då Ediths familj flyttade dit + från Stora Grimön i Vänern. Den enda kända inkorsningen av djur utifrån + är från 1968. Då togs två svart-vit brokiga djur, en hona och en hane, + in i besättningen. Djurantalet i har tidigare legat kring 15-20 men + minskade under de sista åren drastiskt. De sista djuren köptes ut från + ursprungsbesättningen under 2007. + + + I slutet av oktober 2011 godkände Jordbruksverket Föreningen + Gotlandskaninens avelsplan för Mellerudskanin och därmed är + Mellerudskaninen officiellt en svensk husdjursras. Bevarandearbete + organiseras av Föreningen Gotlandskaninen i ett genbankssystem. Aveln + sker i speciella besättningar som föreningen godkänt. Det finns ungefär + 50 sådana besättningar för Mellerudskanin spridda över hela Sverige. De + rapporterar till föreningen vad som sker i besättningen och utfärdar + stamtavlor (genbanksintyg) för de djur som går vidare i avelsarbetet i + gamla eller nya besättningar. + + + Om du är intresserad av att veta mer, eller vill starta en + genbanksbesättning för Mellerudskanin, kontakta genbanksansvarig,{" "} + + mellerudskanin@gotlandskaninen.se + + . ); @@ -299,16 +289,14 @@ export function Medlem() { Bli Medlem -

- Vill du bli medlem i föreningen? Då kan du antingen kontakta - föreningen eller sätta in 200 kr på Föreningen Gotlandskaninens - plusgirokonto 35 03 44-8. Glöm inte att uppge namn och adress. -

-

- Som medlem får man tre gånger om året föreningens medlemstidning - Koharen som innehåller information till medlemmarna, artiklar och - reportage, annonser samt kontaktuppgifter. -

+ Vill du bli medlem i föreningen? Då kan du antingen kontakta föreningen + eller sätta in 200 kr på Föreningen Gotlandskaninens plusgirokonto 35 03 + 44-8. Glöm inte att uppge namn och adress. +
+ + Som medlem får man tre gånger om året föreningens medlemstidning Koharen + som innehåller information till medlemmarna, artiklar och reportage, + annonser samt kontaktuppgifter. ); @@ -321,55 +309,53 @@ export function Kontakt() { Kontakta oss -

- - info@gotlandskaninen.se - - Kontakt med föreningen, annonser och material till hemsidan -

-

- - gotlandskanin@gotlandskaninen.se - - Genbanksansvarig för Gotlandskanin, kassör -

-

- - mellerudskanin@gotlandskaninen.se - - Genbanksansvarig för Mellerudskanin -

-

- - ordforande@gotlandskaninen.se - - Ordförande -

-

- - Tråd om Stamboken online i vårt forum - -

+ + info@gotlandskaninen.se + {" "} + Kontakt med föreningen, annonser och material till hemsidan +
+ + + gotlandskanin@gotlandskaninen.se + {" "} + Genbanksansvarig för Gotlandskanin, kassör + + + + mellerudskanin@gotlandskaninen.se + {" "} + Genbanksansvarig för Mellerudskanin + + + + ordforande@gotlandskaninen.se + {" "} + Ordförande + + + + Tråd om Stamboken online i vårt forum + ); @@ -390,19 +376,17 @@ export function Footer() { -

- Stamboken Online version :{" "} - - {tags.gitBranch} - -

+ Stamboken Online version :{" "} + + {tags.gitBranch} +