As Noah is going to a new school, we have been encouraging him to understand where he is going to be from September. Noah says: βIβm going to the big school and Sofia is going to be in Noddyβsβ.
NS
Encourage activities that help with tasks like holding a pencil, cutting with scissors, and drawing pictures for his new school. Noah could also try writing his name or practicing his basic shapes and letters in preparation for school.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 29
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2656618,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-08-14T10:42:00",
- "notes": "<p>As Noah is going to a new school, we have been encouraging him to understand where he is going to be from September. Noah says: \u201cI\u2019m going to the big school and Sofia is going to be in Noddy\u2019s\u201d.</p><p><br></p><p>NS</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-size: medium;\">Encourage activities that help with tasks like holding a pencil, cutting with scissors, and drawing pictures for his new school. Noah could also try writing his name or practicing his basic shapes and letters in preparation for school.</span></span></p>",
- "frameworkIndicatorCount": 29,
- "signed": false
-}
-
The turtle room went on a trip to the garden centre and Noah was exploring it, talking about colours, what he could smell and what flowers need to grow. Well done Noah!
NS
Ask Noah how she feels when he is surrounded by the flowers and smells. Exploring emotional responses, like, "How does the garden make you feel? Happy or calm?"
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 24
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2656615,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-08-07T14:42:00",
- "notes": "<p>The turtle room went on a trip to the garden centre and Noah was exploring it, talking about colours, what he could smell and what flowers need to grow. Well done Noah!</p><p><br></p><p>NS</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Ask Noah how she feels when he is surrounded by the flowers and smells. Exploring emotional responses, like, \"How does the garden make you feel? Happy or calm?\"</span></span></p>",
- "frameworkIndicatorCount": 24,
- "signed": false
-}
-
Noah was at the mark making area practicing tutting and asked him if he could cut following the dotted lines and so he did. Well done Noah!
NS
carry on providing opportunities for Noah where he can continue strengthening his fingers.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 30
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2643832,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-08-01T10:51:00",
- "notes": "<p>Noah was at the mark making area practicing tutting and asked him if he could cut following the dotted lines and so he did. Well done Noah!</p><p><br></p><p>NS</p><p>carry on providing opportunities for Noah where he can continue strengthening his fingers.</p>",
- "frameworkIndicatorCount": 30,
- "signed": false
-}
-
Today Sophia made some summer drinks out of paper and paint. While she was using her paint brush she also used her index finger to move the paint around the paper.
Next steps: Help improve Sophiaβs pincer grip by adding items to stick onto her artwork while painting.
-
-
-
-
πΈ Images:
-
-
-
-
DCC724DD-0E3C-445D-BB6A-628C355533F2.jpeg
-
Updated: 2025-07-31 12:46:24
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 6
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2646689,
- "media": [
- {
- "id": 794684,
- "fileName": "DCC724DD-0E3C-445D-BB6A-628C355533F2.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2025-07-31T12:46:24.413",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 1047,
- "forename": "Sophia",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 423,
- "forename": "Kyra ",
- "surname": "Philbert-Nurse",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-07-31T10:42:00",
- "notes": "<p>Today Sophia made some summer drinks out of paper and paint. While she was using her paint brush she also used her index finger to move the paint around the paper. </p><p><br></p><p>Next steps: Help improve Sophia\u2019s pincer grip by adding items to stick onto her artwork while painting. </p>",
- "frameworkIndicatorCount": 6,
- "signed": false
-}
-
Noah was playing with the magnetic board when I asked him to find her name. He quickly found it, and then I asked him to locate the letters in him name and write them on the board. As he did, he started saying the phonetic sound for each letter and built his name one by one. Well done Noah!
NS
Continue reinforcing phonetic awareness through songs or games that involve rhyming and sounds.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 25
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2633724,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-07-22T13:39:00",
- "notes": "<p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Noah was playing with the magnetic board when I asked him to find her name. He quickly found it, and then I asked him to locate the letters in him name and write them on the board. As he did, he started saying the phonetic sound for each letter and built his name one by one. Well done Noah!</span></span></p><p><br></p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">NS</span></span></p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Continue reinforcing phonetic awareness through songs or games that involve rhyming and sounds.</span></span></p>",
- "frameworkIndicatorCount": 25,
- "signed": false
-}
-
Noah was drawing and asked me how to hold the pencil as he was holding it with his whole hand. I showed him how I was holding the pencil and he tried to do the same but he could not draw in the same way he was doing earlier.
NS
Prepare activities where Noah can strengthen his fingers, eg. playing with play dough, threading, building with small Lego pieces.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 29
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2632485,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-07-17T14:56:00",
- "notes": "<p>Noah was drawing and asked me how to hold the pencil as he was holding it with his whole hand. I showed him how I was holding the pencil and he tried to do the same but he could not draw in the same way he was doing earlier.</p><p><br></p><p>NS</p><p>Prepare activities where Noah can strengthen his fingers, eg. playing with play dough, threading, building with small Lego pieces.</p>",
- "frameworkIndicatorCount": 29,
- "signed": false
-}
-
This afternoon Sophia was presented with playdough when she began squeezing the dough with one hand while poking the other bit of dough with her other hand. Sophia was very enthusiastic about the playdough and loved the feeling of it.
next steps: encourage Sophia to use her hands and fingers during sensory play with sand or flour etc in order to develop er fine motor skills.
-
-
-
-
πΈ Images:
-
-
-
-
e4e51387-1fee-4129-bd47-e49523b26697.jpeg
-
Updated: 2025-07-15 16:06:04
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2629370,
- "media": [
- {
- "id": 788063,
- "fileName": "e4e51387-1fee-4129-bd47-e49523b26697.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2025-07-15T16:06:04.227",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 1047,
- "forename": "Sophia",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 423,
- "forename": "Kyra ",
- "surname": "Philbert-Nurse",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-07-15T15:25:00",
- "notes": "<p>This afternoon Sophia was presented with playdough when she began squeezing the dough with one hand while poking the other bit of dough with her other hand. Sophia was very enthusiastic about the playdough and loved the feeling of it.</p><p><br></p><p>next steps: encourage Sophia to use her hands and fingers during sensory play with sand or flour etc in order to develop er fine motor skills.</p>",
- "signed": false
-}
-
We were making marks on flour in the messy tray using brushes and Noah drew a figure and said it was number three. Well done Noah!
NS
Let Noah explore how to use different tools to create different numbers or letters.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 23
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2620380,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-07-03T13:20:00",
- "notes": "<p>We were making marks on flour in the messy tray using brushes and Noah drew a figure and said it was number three. Well done Noah!</p><p><br></p><p>NS</p><p>Let Noah explore how to use different tools to create different numbers or letters.</p>",
- "frameworkIndicatorCount": 23,
- "signed": false
-}
-
Noah was playing in the Turtle room and he said the word "beefeater" I asked him if he knew what a beefeater was and he said they ate beef and they lived in the tower of London.
NS
Keep expanding Noah's understanding and knowledge of the city of London, showing him pictures, asking him what he can see and explaining what we are showing.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 20
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2609304,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-06-26T08:15:00",
- "notes": "<p>Noah was playing in the Turtle room and he said the word \"beefeater\" I asked him if he knew what a beefeater was and he said they ate beef and they lived in the tower of London. </p><p><br></p><p>NS</p><p>Keep expanding Noah's understanding and knowledge of the city of London, showing him pictures, asking him what he can see and explaining what we are showing.</p>",
- "frameworkIndicatorCount": 20,
- "signed": false
-}
-
We were going through some of the letters of the alphabet, and one of the teachers showed the picture of an elephant. Noah was asked to find the letter "E" for elephant. He stood up and picked up the right one. Well done, Noah!
NS
Continue with identifying individual letters, especially those in familiar words like names, animals, or favourite objects.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 10
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2601284,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-06-18T13:28:00",
- "notes": "<p>We were going through some of the letters of the alphabet, and one of the teachers showed the picture of an elephant. Noah was asked to find the letter \"E\" for elephant. He stood up and picked up the right one. Well done, Noah!</p><p>NS</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-size: medium;\">Continue with identifying individual letters, especially those in familiar words like names, animals, or favourite objects.</span></span></p>",
- "frameworkIndicatorCount": 10,
- "signed": false
-}
-
We were playing a game where Noah had to throw the dices, count the dots and match them with the right number. Noah could count and match them correctly. Well done Noah!
NS
Encourage Noah to recognise small quantities (1β5) without counting.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 22
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2557679,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-05-02T10:03:00",
- "notes": "<p>We were playing a game where Noah had to throw the dices, count the dots and match them with the right number. Noah could count and match them correctly. Well done Noah!</p><p>NS</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Encourage Noah to recognise small quantities (1\u20135) without counting.</span></span></p>",
- "frameworkIndicatorCount": 22,
- "signed": false
-}
-
During small sports, the children were asked to flip cones with the stick. Noah struggled at first but after a few attempts found the way to flip the cones just using the hickey stick. Well done!
NS
Provide more opportunities for Noah to practice activities involving balance, coordination, and agility.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 23
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2538151,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-04-09T14:13:00",
- "notes": "<p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">During small sports, the children were asked to flip cones with the stick. Noah struggled at first but after a few attempts found the way to flip the cones just using the hickey stick. Well done!</span></span></p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">NS</span></span></p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Provide more opportunities for Noah to practice activities involving balance, coordination, and agility.</span></span></p>",
- "frameworkIndicatorCount": 23,
- "signed": false
-}
-
We were listening to scary, sad and happy music. When listening to scary music, Noah said βBear one - coming with a knifeβ. When we were listening to sad music and I asked him how he felt he said βitβs about scaryβ. When we listened to happy music, Noah started dancing and smiling
well done!
ns
Encourage Noah to describe the music further, Asking questions like, "What made the music sound scary or happy?" or "Can you make a sound that matches the sad music?".
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 17
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2522260,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-03-19T13:42:00",
- "notes": "<p>We were listening to scary, sad and happy music. When listening to scary music, Noah said \u201cBear one - coming with a knife\u201d. When we were listening to sad music and I asked him how he felt he said \u201cit\u2019s about scary\u201d. When we listened to happy music, Noah started dancing and smiling</p><p>well done!</p><p><br></p><p>ns</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; font-size: medium;\">Encourage Noah to describe the music further, Asking questions like, \"What made the music sound scary or happy?\" or \"Can you make a sound that matches the sad music?\".</span></span></p>",
- "frameworkIndicatorCount": 17,
- "signed": false
-}
-
I was playing in the home corner with Noah (hairdressers) and he was brushing my hair, I asked him what he was going to do and he said he was going to wash it and that he needed scissors to cut it.
ns
Discuss hygiene and personal care. Talk about why we wash our hair, why we cut it, and how we take care of our hair. This fosters an understanding of self-care and personal hygiene.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 29
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2504266,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-03-04T13:27:00",
- "notes": "<p>I was playing in the home corner with Noah (hairdressers) and he was brushing my hair, I asked him what he was going to do and he said he was going to wash it and that he needed scissors to cut it. </p><p><br></p><p>ns</p><p><span style=\"color: rgb(0, 0, 0);\"><span style=\"-webkit-tap-highlight-color: rgba(26, 26, 26, 0.3); -webkit-text-size-adjust: auto; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-size: medium;\">Discuss hygiene and personal care. Talk about why we wash our hair, why we cut it, and how we take care of our hair. This fosters an understanding of self-care and personal hygiene.</span></span></p>",
- "frameworkIndicatorCount": 29,
- "signed": false
-}
-
Noah was painting with brushes and he switched the way he was holding it, he used his whole hand at times and then he would try to use thump, index and middle finger.
NS
Keep preparing activities for Noah where he can work on his fine motor skills using different tools, like brushes, pencils or sticks.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 19
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2486490,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-02-17T13:41:00",
- "notes": "<p>Noah was painting with brushes and he switched the way he was holding it, he used his whole hand at times and then he would try to use thump, index and middle finger. </p><p><br></p><p>NS</p><p>Keep preparing activities for Noah where he can work on his fine motor skills using different tools, like brushes, pencils or sticks. </p>",
- "frameworkIndicatorCount": 19,
- "signed": false
-}
-
During circle time, we were talking about opposites, I showed a picture of an open box and Noah said they were going up, so I asked him what was the opposite of open and he said closed. Well done Noah!
NS
Keep showing Noah pictures where he can identify more opposites.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 10
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2450710,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2025-01-09T15:05:00",
- "notes": "<p>During circle time, we were talking about opposites, I showed a picture of an open box and Noah said they were going up, so I asked him what was the opposite of open and he said closed. Well done Noah!</p><p><br></p><p>NS</p><p>Keep showing Noah pictures where he can identify more opposites.</p>",
- "frameworkIndicatorCount": 10,
- "signed": false
-}
-
One of Noahβs friends was trying to put their shoes on, when this child finished putting them on, Noah said βWell done! Im very proud of youβ. Well done Noah!
NS
Keep Encouraging Noah to understand what other people might expect from us and how to manage expectations in a positive way.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 12
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2396198,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-11-06T13:40:00",
- "notes": "<p>One of Noah\u2019s friends was trying to put their shoes on, when this child finished putting them on, Noah said \u201cWell done! Im very proud of you\u201d. Well done Noah!</p><p><br></p><p>NS</p><p>Keep Encouraging Noah to understand what other people might expect from us and how to manage expectations in a positive way.</p>",
- "frameworkIndicatorCount": 12,
- "signed": false
-}
-
During small sports, the children where asked to make a cone stand using a hockey stick. Noah struggled at first and tried to use his other hand but in the end he make the cone stand by just using the stick. Well done Noah!
NS
Keep working on Noah's physical development, particularly on his fine motor skills, for example encouraging him to zip up his coat.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 17
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2386325,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-10-30T16:25:00",
- "notes": "<p>During small sports, the children where asked to make a cone stand using a hockey stick. Noah struggled at first and tried to use his other hand but in the end he make the cone stand by just using the stick. Well done Noah!</p><p><br></p><p>NS</p><p>Keep working on Noah's physical development, particularly on his fine motor skills, for example encouraging him to zip up his coat.</p>",
- "frameworkIndicatorCount": 17,
- "signed": false
-}
-
During circle time, we were practicing prepositional language, and I showed Noah a picture of a teddy standing between two tables. I asked him where the teddy was, and he said that the teddy was between the tables. Well done Noah!
NS
Keep working on prepositions using different objects we can find in the room or in the garden
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 11
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2381857,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-10-23T14:12:00",
- "notes": "<p>During circle time, we were practicing prepositional language, and I showed Noah a picture of a teddy standing between two tables. I asked him where the teddy was, and he said that the teddy was between the tables. Well done Noah!</p><p><br></p><p>NS</p><p>Keep working on prepositions using different objects we can find in the room or in the garden</p>",
- "frameworkIndicatorCount": 11,
- "signed": false
-}
-
During circle time we were talking and showing pictures of the planets, and Noah remembered Saturn.
Well done Noah!
NS
Keep working on Noahβs memory, by preparing activities about the topic we are working on where he is giving a description or a picture and he has to guess.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 12
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2373388,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-10-10T13:52:00",
- "notes": "<p>During circle time we were talking and showing pictures of the planets, and Noah remembered Saturn.</p><p>Well done Noah!</p><p><br></p><p>NS</p><p>Keep working on Noah\u2019s memory, by preparing activities about the topic we are working on where he is giving a description or a picture and he has to guess.</p>",
- "frameworkIndicatorCount": 12,
- "signed": false
-}
-
During circle time, I asked the children in the Turtle room who was going to school, and Noah said he would go to school when he was old.
NS
Keep encouraging Noah to talk about past and future events using the right tenses by asking questions, reading stories that use these tenses.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 9
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2362677,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-10-02T09:18:00",
- "notes": "<p>During circle time, I asked the children in the Turtle room who was going to school, and Noah said he would go to school when he was old. </p><p><br></p><p>NS</p><p>Keep encouraging Noah to talk about past and future events using the right tenses by asking questions, reading stories that use these tenses.</p>",
- "childsVoice": "I'll go to school when I'm old",
- "frameworkIndicatorCount": 9,
- "signed": false
-}
-
Noah was playing at he role play area with one of his friends pretending they were in a restaurant. Noah was bringing toy food to the table and saying that it was Elena's birthday as he put a cake made out of blocks and started singing happy birthday.
NS
Prepare activities for Noah where he can understand his emotions and other's, showing empathy a matching other people's expectations through role play activities or story time.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 13
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2351985,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-09-17T14:45:00",
- "notes": "<p>Noah was playing at he role play area with one of his friends pretending they were in a restaurant. Noah was bringing toy food to the table and saying that it was Elena's birthday as he put a cake made out of blocks and started singing happy birthday.</p><p><br></p><p>NS</p><p>Prepare activities for Noah where he can understand his emotions and other's, showing empathy a matching other people's expectations through role play activities or story time.</p>",
- "frameworkIndicatorCount": 13,
- "signed": false
-}
-
During circle time we were working in numbers and Noah was asked to count and take five big waffles and so he did. Well dine Noah!
NS
Keep working on mathematics by asking Noah to count and give up to ten items.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 16
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2347246,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-09-12T14:06:00",
- "notes": "<p>During circle time we were working in numbers and Noah was asked to count and take five big waffles and so he did. Well dine Noah!</p><p><br></p><p>NS</p><p>Keep working on mathematics by asking Noah to count and give up to ten items. </p>",
- "frameworkIndicatorCount": 16,
- "signed": false
-}
-
Noah is settling in the new room very well, this week he has been exploring and playing with his friends and new teachers.
NS
Keep working on Noahβs confidence in the Turtle room helping him to get used to the new routine.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 13
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2341094,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 208,
- "forename": "Elena",
- "surname": "Blanco Corbacho",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-09-05T17:04:00",
- "notes": "<p>Noah is settling in the new room very well, this week he has been exploring and playing with his friends and new teachers. </p><p><br></p><p>NS</p><p>Keep working on Noah\u2019s confidence in the Turtle room helping him to get used to the new routine.</p>",
- "frameworkIndicatorCount": 13,
- "signed": false
-}
-
During sharing box session, the teacher hold up a book and asked whoβs book is it? Noah replied itβs Noddyβs book as it had a Noddyβs logo on it. Well spotted Noah, great job.
NS: Encourage Noah to continue to recognise logos on items and be able to read it after the teacher.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 8
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2325793,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-08-15T15:08:00",
- "notes": "<p>During sharing box session, the teacher hold up a book and asked who\u2019s book is it? Noah replied it\u2019s Noddy\u2019s book as it had a Noddy\u2019s logo on it. Well spotted Noah, great job.</p><p><br></p><p>NS: Encourage Noah to continue to recognise logos on items and be able to read it after the teacher.</p>",
- "frameworkIndicatorCount": 8,
- "signed": false
-}
-
Noah listens to his teacherβs instructions following the rules during sports activities. He points the red side of the rocket towards his friend and throws it up to her, well done Noah
NS: Encourage Him to participate more in physical activities to improve on his stamina and physical skills.
-
-
-
-
πΈ Images:
-
-
-
-
AB2FE0B6-0932-4179-A3AE-933E05FA8519.jpeg
-
Updated: 2024-08-08 15:42:05
-
-
-
-
466557B6-6ED0-4750-BA37-EC6DF92CB18B.jpeg
-
Updated: 2024-08-08 15:51:25
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 14
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2319312,
- "media": [
- {
- "id": 665519,
- "fileName": "AB2FE0B6-0932-4179-A3AE-933E05FA8519.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-08-08T15:42:05.243",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 665528,
- "fileName": "466557B6-6ED0-4750-BA37-EC6DF92CB18B.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-08-08T15:51:25.377",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-08-08T10:21:00",
- "notes": "<p>Noah listens to his teacher\u2019s instructions following the rules during sports activities. He points the red side of the rocket towards his friend and throws it up to her, well done Noah</p><p><br></p><p>NS: Encourage Him to participate more in physical activities to improve on his stamina and physical skills.</p>",
- "frameworkIndicatorCount": 14,
- "signed": false
-}
-
Noah wears a chef scarf on his head. He says βI am a chefβ and starts to fill in a container with tomato sauce and pour to the plain pasta to make his own tomato pasta. He adds up salt and other ingredients in it to his taste, wow yummy pasta Noah.
NS: Encourage Noah to continue to participate in group activities with new teachers and friends and communicate more.
-
-
-
-
πΈ Images:
-
-
-
-
7268DAC2-8275-47DA-8A0D-FA659F850C31.jpeg
-
Updated: 2024-08-02 18:25:15
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 9
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2313641,
- "media": [
- {
- "id": 663592,
- "fileName": "7268DAC2-8275-47DA-8A0D-FA659F850C31.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-08-02T18:25:15.457",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-08-02T10:16:00",
- "notes": "<p>Noah wears a chef scarf on his head. He says \u201cI am a chef\u201d and starts to fill in a container with tomato sauce and pour to the plain pasta to make his own tomato pasta. He adds up salt and other ingredients in it to his taste, wow yummy pasta Noah.</p><p><br></p><p>NS: Encourage Noah to continue to participate in group activities with new teachers and friends and communicate more.</p>",
- "childsVoice": "I am a chef",
- "frameworkIndicatorCount": 9,
- "signed": false
-}
-
Noah write a letter, folds it and tries posting it but it couldnβt fit it. He then releases that he had to change its position for it to fit in the post box.
NS: To encourage Noah to explore shapes and measure and how things fit together during role plays.
-
-
-
-
πΈ Images:
-
-
-
-
CCE3933F-84FD-4A6D-987A-77993183A054.jpeg
-
Updated: 2024-06-20 17:43:52
-
-
-
-
2A5EE1D8-A113-43F8-9416-316287DE3E8F.jpeg
-
Updated: 2024-06-20 17:43:55
-
-
-
-
80702FD5-DF2C-4EC3-948C-70EBAE7C4BFF.jpeg
-
Updated: 2024-06-20 17:43:54
-
-
-
-
1BC2789D-99B7-4CC5-84F3-AEA1F0CB39B2.jpeg
-
Updated: 2024-06-20 17:43:55
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 10
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2273952,
- "media": [
- {
- "id": 646636,
- "fileName": "CCE3933F-84FD-4A6D-987A-77993183A054.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-06-20T17:43:52.140",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 646637,
- "fileName": "2A5EE1D8-A113-43F8-9416-316287DE3E8F.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-06-20T17:43:55.030",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 646638,
- "fileName": "80702FD5-DF2C-4EC3-948C-70EBAE7C4BFF.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-06-20T17:43:54.147",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 646639,
- "fileName": "1BC2789D-99B7-4CC5-84F3-AEA1F0CB39B2.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-06-20T17:43:55.167",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-06-20T11:07:00",
- "notes": "<p>Noah write a letter, folds it and tries posting it but it couldn\u2019t fit it. He then releases that he had to change its position for it to fit in the post box. </p><p><br></p><p>NS: To encourage Noah to explore shapes and measure and how things fit together during role plays.</p>",
- "frameworkIndicatorCount": 10,
- "signed": false
-}
-
While looking at the pictures of the people who help us, Noah identifies the dentist and explains that they look after our teeth with actions pointing at his teeth. Well done Noah.
NS: Encourage Noah to learn about all different types of people who help us and what they do.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 8
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2264321,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-06-11T11:27:00",
- "notes": "<p>While looking at the pictures of the people who help us, Noah identifies the dentist and explains that they look after our teeth with actions pointing at his teeth. Well done Noah.</p><p><br></p><p>NS: Encourage Noah to learn about all different types of people who help us and what they do.</p>",
- "frameworkIndicatorCount": 8,
- "signed": false
-}
-
The teacher writes Noahβs name on the whiteboard and asks him to copy her to write the first letter of his name βNβ. Noah imitates the teacher by writing a line starting from down going up. Well done Noah keep it up.
NS: Encourage Noah to continue to practice writing to improve on his fine motor skills by writing using different materials.
-
-
-
-
πΈ Images:
-
-
-
-
BA2B3A67-356C-4D22-9FA2-2CF2040EC080.jpeg
-
Updated: 2024-06-07 14:08:26
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 6
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2261241,
- "media": [
- {
- "id": 641257,
- "fileName": "BA2B3A67-356C-4D22-9FA2-2CF2040EC080.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-06-07T14:08:26.693",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-06-06T10:54:00",
- "notes": "<p>The teacher writes Noah\u2019s name on the whiteboard and asks him to copy her to write the first letter of his name \u201cN\u201d. Noah imitates the teacher by writing a line starting from down going up. Well done Noah keep it up.</p><p><br></p><p>NS: Encourage Noah to continue to practice writing to improve on his fine motor skills by writing using different materials.</p>",
- "frameworkIndicatorCount": 6,
- "signed": false
-}
-
Noah enjoyed exploring the paint texture using his hands and the car during the mark making activity while rolling his car from the bottom of the table going upwards the opposite direction from his friends.
NS: Encourage Noah to participate in all activities not just activities of his interest to support his needs through encouragement and praising.
-
-
-
-
πΈ Images:
-
-
-
-
F3411311-E3CE-4A74-84CB-372DA00F80B7.jpeg
-
Updated: 2024-05-31 09:03:01
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 5
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2252932,
- "media": [
- {
- "id": 637961,
- "fileName": "F3411311-E3CE-4A74-84CB-372DA00F80B7.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-05-31T09:03:01.223",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-05-30T10:56:00",
- "notes": "<p>Noah enjoyed exploring the paint texture using his hands and the car during the mark making activity while rolling his car from the bottom of the table going upwards the opposite direction from his friends.</p><p><br></p><p>NS: Encourage Noah to participate in all activities not just activities of his interest to support his needs through encouragement and praising.</p>",
- "frameworkIndicatorCount": 5,
- "signed": false
-}
-
During the traffic light sign activity. I asked Noah to put glue on the black paper and then stick the red, orange and green circles on it. Noah instead glued first the coloured circles and then he placed them on the paper to create his traffic light signs. Well done Noah
NS: I will encourage Noah to continue to participate in different activities to improve on his fine motor skills and ask him to repeat the new words during activities eg traffic light.
-{
- "id": 2234455,
- "media": [
- {
- "id": 630640,
- "fileName": "1715613184982FE8C3F62-2F0C-4A43-8F57-864F5BA9E112.jpeg.jpg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-05-13T16:13:06.103",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 630641,
- "fileName": "171561318498211415BA1-6E38-4D1C-8962-8ED04199856D.jpeg.jpg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-05-13T16:13:06.597",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-05-13T15:39:00",
- "notes": "<p>During the traffic light sign activity. I asked Noah to put glue on the black paper and then stick the red, orange and green circles on it. Noah instead glued first the coloured circles and then he placed them on the paper to create his traffic light signs. Well done Noah</p><p><br></p><p>NS: I will encourage Noah to continue to participate in different activities to improve on his fine motor skills and ask him to repeat the new words during activities eg traffic light.</p>",
- "frameworkIndicatorCount": 3,
- "signed": false
-}
-
During Circle time while sitting on the carpet with the rest of children looking at the different means of transportation pictures. The teacher picks up a motorbike picture and asks Noah what can he see? He replied βMotorcycleβ, clearly. Well done Noah.
NS: I will continue to encourage Noah to expand his knowledge of different means of transportation by asking him simple questions about them to enhance his speech and vocabulary.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 5
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2231987,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 324,
- "forename": "Ruqiya ",
- "surname": "Noor",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-05-10T09:08:00",
- "notes": "<p>During Circle time while sitting on the carpet with the rest of children looking at the different means of transportation pictures. The teacher picks up a motorbike picture and asks Noah what can he see? He replied \u201cMotorcycle\u201d, clearly. Well done Noah.</p><p><br></p><p>NS: I will continue to encourage Noah to expand his knowledge of different means of transportation by asking him simple questions about them to enhance his speech and vocabulary.</p><p><br></p>",
- "childsVoice": "Motorcycle ",
- "frameworkIndicatorCount": 5,
- "signed": false
-}
-
Noah had a great time and followed instructions carefully during small sports. He tried hitting his ball using his cricket bat but was holding the bat with one hand. I showed him how to hold his cricket ball using two hands, he intently observed me and copied the action with ease. Noah smiled and was proud of his achievements.
NS. Hand and eye coordination games/activity such as playing tennis encouraging Noah to hit the ball when thrown at him.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 8
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2225006,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 12,
- "forename": "Rashai",
- "surname": "Campbell",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-04-25T13:05:00",
- "notes": "<p>Noah had a great time and followed instructions carefully <span style=\"font-size: 16px; white-space: pre-wrap;\">during small sports</span>. He tried hitting his ball using his cricket bat but was holding the bat with one hand. I showed him how to hold his cricket ball using two hands, he intently observed me and copied the action with ease. Noah smiled and was proud of his achievements.</p><p><br></p><p>NS. Hand and eye coordination games/activity such as playing tennis encouraging Noah to hit the ball when thrown at him.</p>",
- "frameworkIndicatorCount": 8,
- "signed": false
-}
-
I printed a picture of a baby no different baby stuff and told Noah we were playing a game.
I asked Noah what was it and he said βa babyβ I asked him βWhere is the baby Noah?β And he said βmummyβs tummyβ
I asked Noah what we need to do when the baby does a wee wee and he said βchange nappyβ so he took the picture of the nappy and put it on the baby.
I asked him what do we give the baby if he is crying and he said βdummyβ and put it on the baby.
I asked him what do we give the baby if is hungry and he said βwaterβ and gave him the bottle.
And to finish, I asked him what do we give the baby for sleep time, and he said βteddy bearβ and gave the teddy to the baby.
NS: keep doing games with Noah related to new babies to encourage him to help with the new baby when arrives. E.g Play with baby dolls and ask Noah to change the nappy.
-
-
-
-
πΈ Images:
-
-
-
-
07B7B911-58C7-4998-BBDE-A773351854D5.jpeg
-
Updated: 2024-04-05 10:58:33
-
-
-
-
1073B5D1-D162-4D78-8135-45447BA04CAB.jpeg
-
Updated: 2024-04-05 10:58:33
-
-
-
-
25E15BAA-58B3-47C8-BEC9-D777ED71A0AB.jpeg
-
Updated: 2024-04-05 10:58:36
-
-
-
-
C959CBD6-A829-43AB-87CF-732269921ADB.jpeg
-
Updated: 2024-04-05 10:58:34
-
-
-
-
045D878D-47E3-4EB5-B9DB-36B9B63299E9.jpeg
-
Updated: 2024-04-05 10:58:39
-
-
-
-
6BC18F39-5C1A-43FB-AD64-0D5AB616A292.jpeg
-
Updated: 2024-04-05 10:58:38
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 4
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2199241,
- "media": [
- {
- "id": 617714,
- "fileName": "07B7B911-58C7-4998-BBDE-A773351854D5.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:33.947",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 617715,
- "fileName": "1073B5D1-D162-4D78-8135-45447BA04CAB.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:33.810",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 617716,
- "fileName": "25E15BAA-58B3-47C8-BEC9-D777ED71A0AB.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:36.310",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 617717,
- "fileName": "C959CBD6-A829-43AB-87CF-732269921ADB.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:34.743",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 617718,
- "fileName": "045D878D-47E3-4EB5-B9DB-36B9B63299E9.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:39.740",
- "status": "available",
- "downloadable": true
- },
- {
- "id": 617719,
- "fileName": "6BC18F39-5C1A-43FB-AD64-0D5AB616A292.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-04-05T10:58:38.670",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-04-05T10:59:00",
- "notes": "<p>I printed a picture of a baby no different baby stuff and told Noah we were playing a game.</p><p>I asked Noah what was it and he said \u201ca baby\u201d I asked him \u201cWhere is the baby Noah?\u201d And he said \u201cmummy\u2019s tummy\u201d</p><p><br></p><p>I asked Noah what we need to do when the baby does a wee wee and he said \u201cchange nappy\u201d so he took the picture of the nappy and put it on the baby.</p><p>I asked him what do we give the baby if he is crying and he said \u201cdummy\u201d and put it on the baby.</p><p>I asked him what do we give the baby if is hungry and he said \u201cwater\u201d and gave him the bottle.</p><p>And to finish, I asked him what do we give the baby for sleep time, and he said \u201cteddy bear\u201d and gave the teddy to the baby.</p><p><br></p><p>NS: keep doing games with Noah related to new babies to encourage him to help with the new baby when arrives. E.g Play with baby dolls and ask Noah to change the nappy.</p>",
- "childsVoice": "A baby\nMummy\u2019s tummy\nDummy\nChange nappy\nWater\nTeddy bear ",
- "frameworkIndicatorCount": 4,
- "signed": false
-}
-
Me and Noah were reading βThree little bunniesβ is a book about Peter Rabbit having three little sisters.
While reading the book, Noah said βMummy babyβ and I asked him βIs mummy having a baby?β And Noah said βYes, Noah babyβ
I asked Noah if he is happy and he said βYesβ I asked him what is he going to do with the toys and the new baby and Noah said βsharingβ
NS: keep reading this types of books with Noah to make him feel more familiar with babies and also keep working on his speech while asking and answering questions.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 3
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2194023,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-03-28T12:34:00",
- "notes": "<p>Me and Noah were reading \u201cThree little bunnies\u201d is a book about Peter Rabbit having three little sisters. </p><p>While reading the book, Noah said \u201cMummy baby\u201d and I asked him \u201cIs mummy having a baby?\u201d And Noah said \u201cYes, Noah baby\u201d</p><p><br></p><p>I asked Noah if he is happy and he said \u201cYes\u201d I asked him what is he going to do with the toys and the new baby and Noah said \u201csharing\u201d</p><p><br></p><p>NS: keep reading this types of books with Noah to make him feel more familiar with babies and also keep working on his speech while asking and answering questions. </p>",
- "childsVoice": "Mummy baby. \nYes, Noah baby\nYes\nsharing",
- "frameworkIndicatorCount": 3,
- "signed": false
-}
-
Noah was sitting very nicely with his friend Eli looking at a book.
The book was about jungle animals and had lots on animals on the pages.
Noah started talking to Eli about everything he could see on the pages βThe butterfly is flyingβ βThe Lion is hungryβ
NS: look at books together with Noah and ask him questions about it to encourage him to do longer sentences.
-
-
-
-
πΈ Images:
-
-
-
-
D827391F-6BB7-4F61-B315-FB791E5ADC2F.jpeg
-
Updated: 2024-03-21 11:33:22
-
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2186877,
- "media": [
- {
- "id": 613060,
- "fileName": "D827391F-6BB7-4F61-B315-FB791E5ADC2F.jpeg",
- "type": "image",
- "mimeType": "image/jpeg",
- "updated": "2024-03-21T11:33:22.587",
- "status": "available",
- "downloadable": true
- }
- ],
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-03-21T11:33:00",
- "notes": "<p>Noah was sitting very nicely with his friend Eli looking at a book.</p><p>The book was about jungle animals and had lots on animals on the pages. </p><p>Noah started talking to Eli about everything he could see on the pages \u201cThe butterfly is flying\u201d \u201cThe Lion is hungry\u201d</p><p><br></p><p>NS: look at books together with Noah and ask him questions about it to encourage him to do longer sentences. </p>",
- "childsVoice": "The butterfly is flying.\nThe lion is hungry. ",
- "signed": false
-}
-
I showed Noah flashcards with the different βgolden rulesβ from the classroom.
I showed him βtidying upβ and asked him βwhat are the children doingβ and he said βtidy upβ
Then I showed him a flash card with children sharing toys and asked him the same question and he answered βsharingβ
NS: keep using different flashcards to work on Noahβs speech and remembering the classroom rules.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2181847,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-03-15T16:41:00",
- "notes": "<p>I showed Noah flashcards with the different \u201cgolden rules\u201d from the classroom.</p><p>I showed him \u201ctidying up\u201d and asked him \u201cwhat are the children doing\u201d and he said \u201ctidy up\u201d</p><p>Then I showed him a flash card with children sharing toys and asked him the same question and he answered \u201csharing\u201d</p><p><br></p><p>NS: keep using different flashcards to work on Noah\u2019s speech and remembering the classroom rules.</p>",
- "childsVoice": "Tidy up\nSharing",
- "signed": false
-}
-
I asked him if he could count the magnets he used and counted, βOne, two, fiveβ
I said to Noah, letβs count together and we counted from 1 to five together.
NS: do activities with numbers with Noah to practice his counting.
E.g. Count the Children in the room during circle time.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 12
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2174805,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-03-08T14:02:00",
- "notes": "<p>Today I was playing with Noah with the magnets. </p><p>He said \u201cLook, a tower!\u201d</p><p>I asked him if he could count the magnets he used and counted, \u201cOne, two, five\u201d</p><p>I said to Noah, let\u2019s count together and we counted from 1 to five together. </p><p><br></p><p>NS: do activities with numbers with Noah to practice his counting. </p><p>E.g. Count the Children in the room during circle time. </p>",
- "childsVoice": "ONE TWO FIVE",
- "frameworkIndicatorCount": 12,
- "signed": false
-}
-
This week we have "jungle animals" as the topic of the week.
We were listening to an audio with the jungle animals sounds. In the audio, the person will say the name of the animal and after we listened to the sound they make.
At the end of the audio, they play the sounds in a different order and without saying the name. The gorilla sound came up and Noah said "GORILLA" then the hippopotamus sound and Noah said "HIPPOPOTAMUS"
NS: use animals sounds with Noah to work on his attention and then ask him questions about them and the animals he listened to.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 11
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2155209,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-02-19T16:02:00",
- "notes": "<p>This week we have \"jungle animals\" as the topic of the week.</p><p>We were listening to an audio with the jungle animals sounds. In the audio, the person will say the name of the animal and after we listened to the sound they make.</p><p><br></p><p>At the end of the audio, they play the sounds in a different order and without saying the name. The gorilla sound came up and Noah said \"GORILLA\" then the hippopotamus sound and Noah said \"HIPPOPOTAMUS\" </p><p><br></p><p>NS: use animals sounds with Noah to work on his attention and then ask him questions about them and the animals he listened to. </p><p><br></p>",
- "childsVoice": "Use different animals sounds with Noah to work on his attention and then ask him questions about them and the animals he listened to. ",
- "frameworkIndicatorCount": 11,
- "signed": false
-}
-
Today we wee doing dancing in Octopus room and the teachers made dance moved and asked the children to follow them.
Noah started dancing and coping the teachers moves.
We were giving instructions to the children during the dance and Noah followed them with no distraction.
NS: keep working on Noahβs attention and use dance to encourage him to follow instructions.
-
-
-
-
-
βΉοΈ Additional Information:
-
-
- Code: Snapshot
-
-
- Framework Indicators: 4
-
-
- Type: Snapshot
-
-
-π Raw JSON Data
-
-{
- "id": 2141978,
- "type": "Snapshot",
- "code": "Snapshot",
- "child": {
- "id": 790,
- "forename": "Noah",
- "surname": "Sitaru",
- "hasImage": true
- },
- "author": {
- "id": 344,
- "forename": "Alicia",
- "surname": "Romero Rielo",
- "isStaff": true,
- "hasImage": true
- },
- "startTime": "2024-02-02T14:06:00",
- "notes": "<p>Today we wee doing dancing in Octopus room and the teachers made dance moved and asked the children to follow them. </p><p>Noah started dancing and coping the teachers moves. </p><p>We were giving instructions to the children during the dance and Noah followed them with no distraction. </p><p><br></p><p>NS: keep working on Noah\u2019s attention and use dance to encourage him to follow instructions. </p>",
- "frameworkIndicatorCount": 4,
- "signed": false
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/__init__.py b/src/__init__.py
new file mode 100644
index 0000000..21d9ec0
--- /dev/null
+++ b/src/__init__.py
@@ -0,0 +1,44 @@
+"""
+ParentZone Downloader - Source Package
+
+This package contains the core application modules for the ParentZone Downloader.
+
+Modules:
+ - asset_tracker: Track downloaded assets to avoid re-downloads
+ - auth_manager: Handle authentication with ParentZone API
+ - config_downloader: Configuration-based image downloader
+ - config_snapshot_downloader: Configuration-based snapshot downloader
+ - image_downloader: Download images from ParentZone API
+ - snapshot_downloader: Download snapshots from ParentZone API
+ - webserver: Web server to serve downloaded snapshots
+"""
+
+__version__ = "1.0.0"
+__author__ = "ParentZone Downloader Team"
+
+# Import main classes for easier access
+try:
+ from .asset_tracker import AssetTracker
+ from .auth_manager import AuthManager
+ from .config_downloader import ConfigImageDownloader
+ from .config_snapshot_downloader import ConfigSnapshotDownloader
+ from .image_downloader import ImageDownloader
+ from .snapshot_downloader import SnapshotDownloader
+ from .webserver import SnapshotsWebServer
+
+ __all__ = [
+ "AssetTracker",
+ "AuthManager",
+ "ConfigImageDownloader",
+ "ConfigSnapshotDownloader",
+ "ImageDownloader",
+ "SnapshotDownloader",
+ "SnapshotsWebServer",
+ ]
+
+except ImportError as e:
+ # Handle case where dependencies might not be available
+ __all__ = []
+ import warnings
+
+ warnings.warn(f"Some modules could not be imported: {e}")
diff --git a/asset_tracker.py b/src/asset_tracker.py
similarity index 100%
rename from asset_tracker.py
rename to src/asset_tracker.py
diff --git a/auth_manager.py b/src/auth_manager.py
similarity index 100%
rename from auth_manager.py
rename to src/auth_manager.py
diff --git a/config_downloader.py b/src/config_downloader.py
similarity index 98%
rename from config_downloader.py
rename to src/config_downloader.py
index e550b80..99ee65f 100644
--- a/config_downloader.py
+++ b/src/config_downloader.py
@@ -24,12 +24,12 @@ from tqdm import tqdm
# Import the auth manager and asset tracker
try:
- from auth_manager import AuthManager
+ from src.auth_manager import AuthManager
except ImportError:
AuthManager = None
try:
- from asset_tracker import AssetTracker
+ from src.asset_tracker import AssetTracker
except ImportError:
AssetTracker = None
@@ -453,8 +453,8 @@ Examples:
python config_downloader.py --config config.json
# Create a config file first:
- cp config_example.json my_config.json
- # Edit my_config.json with your API details
+ cp config/config_example.json config/my_config.json
+ # Edit config/my_config.json with your API details
python config_downloader.py --config my_config.json
""",
)
diff --git a/config_snapshot_downloader.py b/src/config_snapshot_downloader.py
similarity index 72%
rename from config_snapshot_downloader.py
rename to src/config_snapshot_downloader.py
index 252bda6..196e8e3 100644
--- a/config_snapshot_downloader.py
+++ b/src/config_snapshot_downloader.py
@@ -16,9 +16,11 @@ from pathlib import Path
# Import the snapshot downloader
try:
- from snapshot_downloader import SnapshotDownloader
+ from src.snapshot_downloader import SnapshotDownloader
except ImportError:
- print("Error: snapshot_downloader.py not found. Please ensure it's in the same directory.")
+ print(
+ "Error: snapshot_downloader.py not found. Please ensure it's in the same directory."
+ )
exit(1)
@@ -35,38 +37,47 @@ class ConfigSnapshotDownloader:
# Create the underlying snapshot downloader
self.downloader = SnapshotDownloader(
- api_url=self.config.get('api_url', 'https://api.parentzone.me'),
- output_dir=self.config.get('output_dir', 'snapshots'),
- api_key=self.config.get('api_key'),
- email=self.config.get('email'),
- password=self.config.get('password')
+ api_url=self.config.get("api_url", "https://api.parentzone.me"),
+ output_dir=self.config.get("output_dir", "snapshots"),
+ api_key=self.config.get("api_key"),
+ email=self.config.get("email"),
+ password=self.config.get("password"),
)
def load_config(self, config_file: str) -> dict:
"""Load configuration from JSON file."""
try:
- with open(config_file, 'r') as f:
+ with open(config_file, "r") as f:
config = json.load(f)
# Validate required authentication
- has_api_key = 'api_key' in config and config['api_key']
- has_credentials = 'email' in config and 'password' in config and config['email'] and config['password']
+ has_api_key = "api_key" in config and config["api_key"]
+ has_credentials = (
+ "email" in config
+ and "password" in config
+ and config["email"]
+ and config["password"]
+ )
if not has_api_key and not has_credentials:
- raise ValueError("Either 'api_key' or both 'email' and 'password' must be provided in config")
+ raise ValueError(
+ "Either 'api_key' or both 'email' and 'password' must be provided in config"
+ )
# Set defaults for optional fields
- config.setdefault('api_url', 'https://api.parentzone.me')
- config.setdefault('output_dir', 'snapshots')
- config.setdefault('type_ids', [15])
- config.setdefault('max_pages', None)
+ config.setdefault("api_url", "https://api.parentzone.me")
+ config.setdefault("output_dir", "snapshots")
+ config.setdefault("type_ids", [15])
+ config.setdefault("max_pages", None)
# Set default date range (last year) if not specified
- if 'date_from' not in config or not config['date_from']:
- config['date_from'] = (datetime.now() - timedelta(days=365)).strftime("%Y-%m-%d")
+ if "date_from" not in config or not config["date_from"]:
+ config["date_from"] = (datetime.now() - timedelta(days=365)).strftime(
+ "%Y-%m-%d"
+ )
- if 'date_to' not in config or not config['date_to']:
- config['date_to'] = datetime.now().strftime("%Y-%m-%d")
+ if "date_to" not in config or not config["date_to"]:
+ config["date_to"] = datetime.now().strftime("%Y-%m-%d")
return config
@@ -77,17 +88,14 @@ class ConfigSnapshotDownloader:
def setup_logging(self):
"""Setup logging configuration."""
- output_dir = Path(self.config['output_dir'])
+ output_dir = Path(self.config["output_dir"])
output_dir.mkdir(exist_ok=True)
- log_file = output_dir / 'snapshots.log'
+ log_file = output_dir / "snapshots.log"
logging.basicConfig(
level=logging.INFO,
- format='%(asctime)s - %(levelname)s - %(message)s',
- handlers=[
- logging.FileHandler(log_file),
- logging.StreamHandler()
- ]
+ format="%(asctime)s - %(levelname)s - %(message)s",
+ handlers=[logging.FileHandler(log_file), logging.StreamHandler()],
)
self.logger = logging.getLogger(__name__)
@@ -99,19 +107,21 @@ class ConfigSnapshotDownloader:
Path to the generated HTML file
"""
self.logger.info("Starting snapshot download with configuration")
- self.logger.info(f"Date range: {self.config['date_from']} to {self.config['date_to']}")
+ self.logger.info(
+ f"Date range: {self.config['date_from']} to {self.config['date_to']}"
+ )
self.logger.info(f"Type IDs: {self.config['type_ids']}")
self.logger.info(f"Output directory: {self.config['output_dir']}")
- if self.config.get('max_pages'):
+ if self.config.get("max_pages"):
self.logger.info(f"Max pages limit: {self.config['max_pages']}")
try:
html_file = await self.downloader.download_snapshots(
- type_ids=self.config['type_ids'],
- date_from=self.config['date_from'],
- date_to=self.config['date_to'],
- max_pages=self.config.get('max_pages')
+ type_ids=self.config["type_ids"],
+ date_from=self.config["date_from"],
+ date_to=self.config["date_to"],
+ max_pages=self.config.get("max_pages"),
)
return html_file
@@ -131,10 +141,10 @@ class ConfigSnapshotDownloader:
print(f"Date To: {self.config['date_to']}")
print(f"Type IDs: {self.config['type_ids']}")
- auth_method = "API Key" if self.config.get('api_key') else "Email/Password"
+ auth_method = "API Key" if self.config.get("api_key") else "Email/Password"
print(f"Authentication: {auth_method}")
- if self.config.get('max_pages'):
+ if self.config.get("max_pages"):
print(f"Max Pages: {self.config['max_pages']}")
print("=" * 60)
@@ -151,11 +161,11 @@ def create_example_config():
"max_pages": null,
"api_key": "your-api-key-here",
"email": "your-email@example.com",
- "password": "your-password-here"
+ "password": "your-password-here",
}
config_file = Path("snapshot_config_example.json")
- with open(config_file, 'w') as f:
+ with open(config_file, "w") as f:
json.dump(example_config, f, indent=2)
print(f"β Example configuration created: {config_file}")
@@ -196,30 +206,27 @@ Notes:
- 'date_from' and 'date_to' default to last year if not specified
- 'type_ids' defaults to [15] (snapshot type)
- 'max_pages' limits pages fetched (useful for testing)
- """
+ """,
+ )
+
+ parser.add_argument("--config", help="Path to the JSON configuration file")
+
+ parser.add_argument(
+ "--create-example",
+ action="store_true",
+ help="Create an example configuration file and exit",
)
parser.add_argument(
- '--config',
- help='Path to the JSON configuration file'
+ "--show-config",
+ action="store_true",
+ help="Show configuration summary before downloading",
)
parser.add_argument(
- '--create-example',
- action='store_true',
- help='Create an example configuration file and exit'
- )
-
- parser.add_argument(
- '--show-config',
- action='store_true',
- help='Show configuration summary before downloading'
- )
-
- parser.add_argument(
- '--debug',
- action='store_true',
- help='Enable debug mode with detailed server response logging'
+ "--debug",
+ action="store_true",
+ help="Enable debug mode with detailed server response logging",
)
args = parser.parse_args()
diff --git a/image_downloader.py b/src/image_downloader.py
similarity index 67%
rename from image_downloader.py
rename to src/image_downloader.py
index a1db7b2..c978285 100644
--- a/image_downloader.py
+++ b/src/image_downloader.py
@@ -26,20 +26,30 @@ import hashlib
# Import the auth manager and asset tracker
try:
- from auth_manager import AuthManager
+ from src.auth_manager import AuthManager
except ImportError:
AuthManager = None
try:
- from asset_tracker import AssetTracker
+ from src.asset_tracker import AssetTracker
except ImportError:
AssetTracker = None
class ImageDownloader:
- def __init__(self, api_url: str, list_endpoint: str, download_endpoint: str,
- output_dir: str, max_concurrent: int = 5, timeout: int = 30, api_key: str = None,
- email: str = None, password: str = None, track_assets: bool = True):
+ def __init__(
+ self,
+ api_url: str,
+ list_endpoint: str,
+ download_endpoint: str,
+ output_dir: str,
+ max_concurrent: int = 5,
+ timeout: int = 30,
+ api_key: str = None,
+ email: str = None,
+ password: str = None,
+ track_assets: bool = True,
+ ):
"""
Initialize the image downloader.
@@ -55,9 +65,9 @@ class ImageDownloader:
password: Password for login authentication
track_assets: Whether to enable asset tracking to avoid re-downloads
"""
- self.api_url = api_url.rstrip('/')
- self.list_endpoint = list_endpoint.lstrip('/')
- self.download_endpoint = download_endpoint.lstrip('/')
+ self.api_url = api_url.rstrip("/")
+ self.list_endpoint = list_endpoint.lstrip("/")
+ self.download_endpoint = download_endpoint.lstrip("/")
self.output_dir = Path(output_dir)
self.max_concurrent = max_concurrent
self.timeout = timeout
@@ -72,11 +82,11 @@ class ImageDownloader:
# Setup logging
logging.basicConfig(
level=logging.INFO,
- format='%(asctime)s - %(levelname)s - %(message)s',
+ format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
- logging.FileHandler(self.output_dir / 'download.log'),
- logging.StreamHandler()
- ]
+ logging.FileHandler(self.output_dir / "download.log"),
+ logging.StreamHandler(),
+ ],
)
self.logger = logging.getLogger(__name__)
@@ -86,17 +96,14 @@ class ImageDownloader:
self.asset_tracker = AssetTracker(storage_dir=str(self.output_dir))
self.logger.info("Asset tracking enabled")
elif track_assets:
- self.logger.warning("Asset tracking requested but AssetTracker not available")
+ self.logger.warning(
+ "Asset tracking requested but AssetTracker not available"
+ )
else:
self.logger.info("Asset tracking disabled")
# Track download statistics
- self.stats = {
- 'total': 0,
- 'successful': 0,
- 'failed': 0,
- 'skipped': 0
- }
+ self.stats = {"total": 0, "successful": 0, "failed": 0, "skipped": 0}
async def authenticate(self):
"""Perform login authentication if credentials are provided."""
@@ -111,10 +118,16 @@ class ImageDownloader:
self.logger.error("Login authentication failed")
raise Exception("Login authentication failed")
elif self.email or self.password:
- self.logger.warning("Both email and password must be provided for login authentication")
- raise Exception("Both email and password must be provided for login authentication")
+ self.logger.warning(
+ "Both email and password must be provided for login authentication"
+ )
+ raise Exception(
+ "Both email and password must be provided for login authentication"
+ )
- async def get_asset_list(self, session: aiohttp.ClientSession) -> List[Dict[str, Any]]:
+ async def get_asset_list(
+ self, session: aiohttp.ClientSession
+ ) -> List[Dict[str, Any]]:
"""
Fetch the list of assets from the API.
@@ -132,13 +145,15 @@ class ImageDownloader:
# Use API key if provided
if self.api_key:
- headers['x-api-key'] = self.api_key
+ headers["x-api-key"] = self.api_key
# Use login authentication if provided
elif self.auth_manager and self.auth_manager.is_authenticated():
headers.update(self.auth_manager.get_auth_headers())
- async with session.get(url, headers=headers, timeout=self.timeout) as response:
+ async with session.get(
+ url, headers=headers, timeout=self.timeout
+ ) as response:
response.raise_for_status()
data = await response.json()
@@ -147,12 +162,12 @@ class ImageDownloader:
assets = data
elif isinstance(data, dict):
# Common patterns for API responses
- if 'data' in data:
- assets = data['data']
- elif 'results' in data:
- assets = data['results']
- elif 'items' in data:
- assets = data['items']
+ if "data" in data:
+ assets = data["data"]
+ elif "results" in data:
+ assets = data["results"]
+ elif "items" in data:
+ assets = data["items"]
else:
assets = [data] # Single asset
else:
@@ -179,7 +194,7 @@ class ImageDownloader:
asset_id = None
# Common field names for asset identifiers
- id_fields = ['id', 'asset_id', 'image_id', 'file_id', 'uuid', 'key']
+ id_fields = ["id", "asset_id", "image_id", "file_id", "uuid", "key"]
for field in id_fields:
if field in asset:
asset_id = asset[field]
@@ -192,12 +207,11 @@ class ImageDownloader:
# Build download URL with required parameters
from urllib.parse import urlencode
- params = {
- 'key': self.api_key,
- 'u': asset.get('updated', '')
- }
+ params = {"key": self.api_key, "u": asset.get("updated", "")}
- download_url = urljoin(self.api_url, f"/v1/media/{asset_id}/full?{urlencode(params)}")
+ download_url = urljoin(
+ self.api_url, f"/v1/media/{asset_id}/full?{urlencode(params)}"
+ )
return download_url
def get_filename(self, asset: Dict[str, Any], url: str) -> str:
@@ -212,27 +226,27 @@ class ImageDownloader:
Filename for the asset
"""
# Try to get filename from asset metadata
- if 'fileName' in asset:
- filename = asset['fileName']
- elif 'filename' in asset:
- filename = asset['filename']
- elif 'name' in asset:
- filename = asset['name']
- elif 'title' in asset:
- filename = asset['title']
+ if "fileName" in asset:
+ filename = asset["fileName"]
+ elif "filename" in asset:
+ filename = asset["filename"]
+ elif "name" in asset:
+ filename = asset["name"]
+ elif "title" in asset:
+ filename = asset["title"]
else:
# Extract filename from URL
parsed_url = urlparse(url)
filename = os.path.basename(parsed_url.path)
# If no extension, try to get it from content-type or add default
- if '.' not in filename:
- if 'mimeType' in asset:
- ext = self._get_extension_from_mime(asset['mimeType'])
- elif 'content_type' in asset:
- ext = self._get_extension_from_mime(asset['content_type'])
+ if "." not in filename:
+ if "mimeType" in asset:
+ ext = self._get_extension_from_mime(asset["mimeType"])
+ elif "content_type" in asset:
+ ext = self._get_extension_from_mime(asset["content_type"])
else:
- ext = '.jpg' # Default extension
+ ext = ".jpg" # Default extension
filename += ext
# Sanitize filename
@@ -251,35 +265,39 @@ class ImageDownloader:
def _get_extension_from_mime(self, mime_type: str) -> str:
"""Get file extension from MIME type."""
mime_to_ext = {
- 'image/jpeg': '.jpg',
- 'image/jpg': '.jpg',
- 'image/png': '.png',
- 'image/gif': '.gif',
- 'image/webp': '.webp',
- 'image/bmp': '.bmp',
- 'image/tiff': '.tiff',
- 'image/svg+xml': '.svg'
+ "image/jpeg": ".jpg",
+ "image/jpg": ".jpg",
+ "image/png": ".png",
+ "image/gif": ".gif",
+ "image/webp": ".webp",
+ "image/bmp": ".bmp",
+ "image/tiff": ".tiff",
+ "image/svg+xml": ".svg",
}
- return mime_to_ext.get(mime_type.lower(), '.jpg')
+ return mime_to_ext.get(mime_type.lower(), ".jpg")
def _sanitize_filename(self, filename: str) -> str:
"""Sanitize filename by removing invalid characters."""
# Remove or replace invalid characters
invalid_chars = '<>:"/\\|?*'
for char in invalid_chars:
- filename = filename.replace(char, '_')
+ filename = filename.replace(char, "_")
# Remove leading/trailing spaces and dots
- filename = filename.strip('. ')
+ filename = filename.strip(". ")
# Ensure filename is not empty
if not filename:
- filename = 'image'
+ filename = "image"
return filename
- async def download_asset(self, session: aiohttp.ClientSession, asset: Dict[str, Any],
- semaphore: asyncio.Semaphore) -> bool:
+ async def download_asset(
+ self,
+ session: aiohttp.ClientSession,
+ asset: Dict[str, Any],
+ semaphore: asyncio.Semaphore,
+ ) -> bool:
"""
Download a single asset.
@@ -300,7 +318,7 @@ class ImageDownloader:
# Check if file already exists and we're not tracking assets
if filepath.exists() and not self.asset_tracker:
self.logger.info(f"Skipping {filename} (already exists)")
- self.stats['skipped'] += 1
+ self.stats["skipped"] += 1
return True
self.logger.info(f"Downloading {filename} from {download_url}")
@@ -309,34 +327,46 @@ class ImageDownloader:
response.raise_for_status()
# Get content type to verify it's an image
- content_type = response.headers.get('content-type', '')
- if not content_type.startswith('image/'):
- self.logger.warning(f"Content type is not an image: {content_type}")
+ content_type = response.headers.get("content-type", "")
+ if not content_type.startswith("image/"):
+ self.logger.warning(
+ f"Content type is not an image: {content_type}"
+ )
# Download the file
- async with aiofiles.open(filepath, 'wb') as f:
+ async with aiofiles.open(filepath, "wb") as f:
async for chunk in response.content.iter_chunked(8192):
await f.write(chunk)
# Set file modification time to match the updated timestamp
- if 'updated' in asset:
+ if "updated" in asset:
try:
from datetime import datetime
import os
+
# Parse the ISO timestamp
- updated_time = datetime.fromisoformat(asset['updated'].replace('Z', '+00:00'))
+ updated_time = datetime.fromisoformat(
+ asset["updated"].replace("Z", "+00:00")
+ )
# Set file modification time
- os.utime(filepath, (updated_time.timestamp(), updated_time.timestamp()))
- self.logger.info(f"Set file modification time to {asset['updated']}")
+ os.utime(
+ filepath,
+ (updated_time.timestamp(), updated_time.timestamp()),
+ )
+ self.logger.info(
+ f"Set file modification time to {asset['updated']}"
+ )
except Exception as e:
- self.logger.warning(f"Failed to set file modification time: {e}")
+ self.logger.warning(
+ f"Failed to set file modification time: {e}"
+ )
# Mark asset as downloaded in tracker
if self.asset_tracker:
self.asset_tracker.mark_asset_downloaded(asset, filepath, True)
self.logger.info(f"Successfully downloaded {filename}")
- self.stats['successful'] += 1
+ self.stats["successful"] += 1
return True
except Exception as e:
@@ -347,8 +377,10 @@ class ImageDownloader:
filepath = self.output_dir / filename
self.asset_tracker.mark_asset_downloaded(asset, filepath, False)
- self.logger.error(f"Failed to download asset {asset.get('id', 'unknown')}: {e}")
- self.stats['failed'] += 1
+ self.logger.error(
+ f"Failed to download asset {asset.get('id', 'unknown')}: {e}"
+ )
+ self.stats["failed"] += 1
return False
async def download_all_assets(self, force_redownload: bool = False):
@@ -364,7 +396,9 @@ class ImageDownloader:
connector = aiohttp.TCPConnector(limit=100, limit_per_host=30)
timeout = aiohttp.ClientTimeout(total=self.timeout)
- async with aiohttp.ClientSession(connector=connector, timeout=timeout) as session:
+ async with aiohttp.ClientSession(
+ connector=connector, timeout=timeout
+ ) as session:
try:
# Perform authentication if needed
await self.authenticate()
@@ -380,24 +414,27 @@ class ImageDownloader:
# Filter for new/modified assets if tracking is enabled
if self.asset_tracker and not force_redownload:
assets = self.asset_tracker.get_new_assets(all_assets)
- self.logger.info(f"Found {len(assets)} new/modified assets to download")
+ self.logger.info(
+ f"Found {len(assets)} new/modified assets to download"
+ )
if len(assets) == 0:
self.logger.info("All assets are up to date!")
return
else:
assets = all_assets
if force_redownload:
- self.logger.info("Force redownload enabled - downloading all assets")
+ self.logger.info(
+ "Force redownload enabled - downloading all assets"
+ )
- self.stats['total'] = len(assets)
+ self.stats["total"] = len(assets)
# Create semaphore to limit concurrent downloads
semaphore = asyncio.Semaphore(self.max_concurrent)
# Create tasks for all downloads
tasks = [
- self.download_asset(session, asset, semaphore)
- for asset in assets
+ self.download_asset(session, asset, semaphore) for asset in assets
]
# Download all assets with progress bar
@@ -405,11 +442,13 @@ class ImageDownloader:
for coro in asyncio.as_completed(tasks):
result = await coro
pbar.update(1)
- pbar.set_postfix({
- 'Success': self.stats['successful'],
- 'Failed': self.stats['failed'],
- 'Skipped': self.stats['skipped']
- })
+ pbar.set_postfix(
+ {
+ "Success": self.stats["successful"],
+ "Failed": self.stats["failed"],
+ "Skipped": self.stats["skipped"],
+ }
+ )
except Exception as e:
self.logger.error(f"Error during download process: {e}")
@@ -441,84 +480,75 @@ Examples:
--output-dir "./images" \\
--max-concurrent 10 \\
--timeout 60
- """
+ """,
)
parser.add_argument(
- '--api-url',
+ "--api-url",
required=True,
- help='Base URL of the API (e.g., https://api.example.com)'
+ help="Base URL of the API (e.g., https://api.example.com)",
)
parser.add_argument(
- '--list-endpoint',
+ "--list-endpoint",
required=True,
- help='Endpoint to get the list of assets (e.g., /assets or /images)'
+ help="Endpoint to get the list of assets (e.g., /assets or /images)",
)
parser.add_argument(
- '--download-endpoint',
+ "--download-endpoint",
required=True,
- help='Endpoint to download individual assets (e.g., /download or /assets)'
+ help="Endpoint to download individual assets (e.g., /download or /assets)",
)
parser.add_argument(
- '--output-dir',
- required=True,
- help='Directory to save downloaded images'
+ "--output-dir", required=True, help="Directory to save downloaded images"
)
parser.add_argument(
- '--max-concurrent',
+ "--max-concurrent",
type=int,
default=5,
- help='Maximum number of concurrent downloads (default: 5)'
+ help="Maximum number of concurrent downloads (default: 5)",
)
parser.add_argument(
- '--timeout',
+ "--timeout",
type=int,
default=30,
- help='Request timeout in seconds (default: 30)'
+ help="Request timeout in seconds (default: 30)",
)
parser.add_argument(
- '--api-key',
- help='API key for authentication (x-api-key header)'
+ "--api-key", help="API key for authentication (x-api-key header)"
+ )
+
+ parser.add_argument("--email", help="Email for login authentication")
+
+ parser.add_argument("--password", help="Password for login authentication")
+
+ parser.add_argument(
+ "--no-tracking",
+ action="store_true",
+ help="Disable asset tracking (will re-download all assets)",
)
parser.add_argument(
- '--email',
- help='Email for login authentication'
+ "--force-redownload",
+ action="store_true",
+ help="Force re-download of all assets, even if already tracked",
)
parser.add_argument(
- '--password',
- help='Password for login authentication'
+ "--show-stats",
+ action="store_true",
+ help="Show asset tracking statistics and exit",
)
parser.add_argument(
- '--no-tracking',
- action='store_true',
- help='Disable asset tracking (will re-download all assets)'
- )
-
- parser.add_argument(
- '--force-redownload',
- action='store_true',
- help='Force re-download of all assets, even if already tracked'
- )
-
- parser.add_argument(
- '--show-stats',
- action='store_true',
- help='Show asset tracking statistics and exit'
- )
-
- parser.add_argument(
- '--cleanup',
- action='store_true',
- help='Clean up metadata for missing files and exit'
+ "--cleanup",
+ action="store_true",
+ help="Clean up metadata for missing files and exit",
)
args = parser.parse_args()
@@ -546,11 +576,13 @@ Examples:
api_key=args.api_key,
email=args.email,
password=args.password,
- track_assets=not args.no_tracking
+ track_assets=not args.no_tracking,
)
try:
- asyncio.run(downloader.download_all_assets(force_redownload=args.force_redownload))
+ asyncio.run(
+ downloader.download_all_assets(force_redownload=args.force_redownload)
+ )
except KeyboardInterrupt:
print("\nDownload interrupted by user")
except Exception as e:
diff --git a/snapshot_downloader.py b/src/snapshot_downloader.py
similarity index 76%
rename from snapshot_downloader.py
rename to src/snapshot_downloader.py
index 0e2aa9d..5c8e82c 100644
--- a/snapshot_downloader.py
+++ b/src/snapshot_downloader.py
@@ -21,15 +21,21 @@ import aiofiles
# Import the auth manager
try:
- from auth_manager import AuthManager
+ from src.auth_manager import AuthManager
except ImportError:
AuthManager = None
class SnapshotDownloader:
- def __init__(self, api_url: str = "https://api.parentzone.me",
- output_dir: str = "snapshots", api_key: str = None,
- email: str = None, password: str = None, debug_mode: bool = False):
+ def __init__(
+ self,
+ api_url: str = "https://api.parentzone.me",
+ output_dir: str = "snapshots",
+ api_key: str = None,
+ email: str = None,
+ password: str = None,
+ debug_mode: bool = False,
+ ):
"""
Initialize the snapshot downloader.
@@ -41,7 +47,7 @@ class SnapshotDownloader:
password: Password for login authentication
debug_mode: Enable detailed server response logging
"""
- self.api_url = api_url.rstrip('/')
+ self.api_url = api_url.rstrip("/")
self.snapshots_endpoint = "/v1/posts"
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
@@ -62,39 +68,36 @@ class SnapshotDownloader:
# Standard headers based on the curl command
self.headers = {
- 'accept': 'application/json, text/plain, */*',
- 'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8,ro;q=0.7',
- 'origin': 'https://parentzone.me',
- 'priority': 'u=1, i',
- 'sec-ch-ua': '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"',
- 'sec-ch-ua-mobile': '?0',
- 'sec-ch-ua-platform': '"macOS"',
- 'sec-fetch-dest': 'empty',
- 'sec-fetch-mode': 'cors',
- 'sec-fetch-site': 'same-site',
- 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
- 'x-client-version': '3.54.0'
+ "accept": "application/json, text/plain, */*",
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8,ro;q=0.7",
+ "origin": "https://parentzone.me",
+ "priority": "u=1, i",
+ "sec-ch-ua": '"Not;A=Brand";v="99", "Google Chrome";v="139", "Chromium";v="139"',
+ "sec-ch-ua-mobile": "?0",
+ "sec-ch-ua-platform": '"macOS"',
+ "sec-fetch-dest": "empty",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-site": "same-site",
+ "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
+ "x-client-version": "3.54.0",
}
# Statistics
self.stats = {
- 'total_snapshots': 0,
- 'pages_fetched': 0,
- 'failed_requests': 0,
- 'generated_files': 0
+ "total_snapshots": 0,
+ "pages_fetched": 0,
+ "failed_requests": 0,
+ "generated_files": 0,
}
def setup_logging(self):
"""Setup logging configuration."""
- log_file = self.output_dir / 'snapshots.log'
+ log_file = self.output_dir / "snapshots.log"
logging.basicConfig(
level=logging.INFO,
- format='%(asctime)s - %(levelname)s - %(message)s',
- handlers=[
- logging.FileHandler(log_file),
- logging.StreamHandler()
- ]
+ format="%(asctime)s - %(levelname)s - %(message)s",
+ handlers=[logging.FileHandler(log_file), logging.StreamHandler()],
)
self.logger = logging.getLogger(__name__)
@@ -109,8 +112,8 @@ class SnapshotDownloader:
self.logger.info("Login authentication successful")
# Use the API key from auth manager
auth_headers = self.auth_manager.get_auth_headers()
- if 'x-api-key' in auth_headers:
- self.api_key = auth_headers['x-api-key']
+ if "x-api-key" in auth_headers:
+ self.api_key = auth_headers["x-api-key"]
else:
self.logger.error("Login authentication failed")
raise Exception("Login authentication failed")
@@ -120,18 +123,21 @@ class SnapshotDownloader:
headers = self.headers.copy()
if self.api_key:
- headers['x-api-key'] = self.api_key
+ headers["x-api-key"] = self.api_key
elif self.auth_manager and self.auth_manager.is_authenticated():
headers.update(self.auth_manager.get_auth_headers())
return headers
- async def fetch_snapshots_page(self, session: aiohttp.ClientSession,
- type_ids: List[int] = [15],
- date_from: str = "2021-10-18",
- date_to: str = None,
- cursor: str = None,
- per_page: int = 100) -> Dict[str, Any]:
+ async def fetch_snapshots_page(
+ self,
+ session: aiohttp.ClientSession,
+ type_ids: List[int] = [15],
+ date_from: str = "2021-10-18",
+ date_to: str = None,
+ cursor: str = None,
+ per_page: int = 100,
+ ) -> Dict[str, Any]:
"""
Fetch a single page of snapshots from the API using cursor-based pagination.
@@ -151,17 +157,17 @@ class SnapshotDownloader:
# Build query parameters
params = {
- 'dateFrom': date_from,
- 'dateTo': date_to,
+ "dateFrom": date_from,
+ "dateTo": date_to,
}
# Add cursor for pagination (skip for first request)
if cursor:
- params['cursor'] = cursor
+ params["cursor"] = cursor
# Add type IDs - API expects typeIDs[]=15 format
for type_id in type_ids:
- params[f'typeIDs[]'] = type_id
+ params[f"typeIDs[]"] = type_id
# Build URL with parameters
query_string = urlencode(params, doseq=True)
@@ -184,21 +190,25 @@ class SnapshotDownloader:
print(f"Status Code: {response.status}")
print(f"Headers: {dict(response.headers)}")
print(f"Response Type: {type(data)}")
- print(f"Response Keys: {list(data.keys()) if isinstance(data, dict) else 'Not a dict'}")
+ print(
+ f"Response Keys: {list(data.keys()) if isinstance(data, dict) else 'Not a dict'}"
+ )
print(f"Posts count: {len(data.get('posts', []))}")
print(f"Cursor: {data.get('cursor', 'None')}")
- if len(data.get('posts', [])) <= 3: # Only print full data if few posts
+ if (
+ len(data.get("posts", [])) <= 3
+ ): # Only print full data if few posts
print(f"Full Response Data:")
print(json.dumps(data, indent=2, default=str))
print("=" * 50)
# The API returns snapshots in 'posts' field
- snapshots = data.get('posts', [])
- cursor_value = data.get('cursor')
+ snapshots = data.get("posts", [])
+ cursor_value = data.get("cursor")
page_info = f"cursor: {cursor[:20]}..." if cursor else "first page"
self.logger.info(f"Retrieved {len(snapshots)} snapshots ({page_info})")
- self.stats['pages_fetched'] += 1
+ self.stats["pages_fetched"] += 1
# Return the actual API response format
return data
@@ -206,14 +216,17 @@ class SnapshotDownloader:
except Exception as e:
page_info = f"cursor: {cursor[:20]}..." if cursor else "first page"
self.logger.error(f"Failed to fetch snapshots ({page_info}): {e}")
- self.stats['failed_requests'] += 1
+ self.stats["failed_requests"] += 1
raise
- async def fetch_all_snapshots(self, session: aiohttp.ClientSession,
- type_ids: List[int] = [15],
- date_from: str = "2021-10-18",
- date_to: str = None,
- max_pages: int = None) -> List[Dict[str, Any]]:
+ async def fetch_all_snapshots(
+ self,
+ session: aiohttp.ClientSession,
+ type_ids: List[int] = [15],
+ date_from: str = "2021-10-18",
+ date_to: str = None,
+ max_pages: int = None,
+ ) -> List[Dict[str, Any]]:
"""
Fetch all snapshots across all pages using cursor-based pagination.
@@ -231,7 +244,9 @@ class SnapshotDownloader:
cursor = None
page_count = 0
- self.logger.info(f"Starting snapshot fetch from {date_from} to {date_to or 'now'}")
+ self.logger.info(
+ f"Starting snapshot fetch from {date_from} to {date_to or 'now'}"
+ )
while True:
page_count += 1
@@ -246,17 +261,19 @@ class SnapshotDownloader:
)
# Extract snapshots from response
- snapshots = response.get('posts', [])
- new_cursor = response.get('cursor')
+ snapshots = response.get("posts", [])
+ new_cursor = response.get("cursor")
if not snapshots:
self.logger.info("No more snapshots found (empty posts array)")
break
all_snapshots.extend(snapshots)
- self.stats['total_snapshots'] += len(snapshots)
+ self.stats["total_snapshots"] += len(snapshots)
- self.logger.info(f"Page {page_count}: {len(snapshots)} snapshots (total: {len(all_snapshots)})")
+ self.logger.info(
+ f"Page {page_count}: {len(snapshots)} snapshots (total: {len(all_snapshots)})"
+ )
# If no cursor returned, we've reached the end
if not new_cursor:
@@ -273,7 +290,9 @@ class SnapshotDownloader:
self.logger.info(f"Total snapshots fetched: {len(all_snapshots)}")
return all_snapshots
- async def format_snapshot_html(self, snapshot: Dict[str, Any], session: aiohttp.ClientSession) -> str:
+ async def format_snapshot_html(
+ self, snapshot: Dict[str, Any], session: aiohttp.ClientSession
+ ) -> str:
"""
Format a single snapshot as HTML.
@@ -284,34 +303,46 @@ class SnapshotDownloader:
HTML string for the snapshot
"""
# Extract key information from ParentZone snapshot format
- snapshot_id = snapshot.get('id', 'unknown')
- content = snapshot.get('notes', '') # Don't escape HTML in notes field
- start_time = snapshot.get('startTime', '')
- snapshot_type = snapshot.get('type', 'Snapshot')
+ snapshot_id = snapshot.get("id", "unknown")
+ content = snapshot.get("notes", "") # Don't escape HTML in notes field
+ start_time = snapshot.get("startTime", "")
+ snapshot_type = snapshot.get("type", "Snapshot")
# Format dates
- start_date = self.format_date(start_time) if start_time else 'Unknown'
+ start_date = self.format_date(start_time) if start_time else "Unknown"
# Extract additional information
- author = snapshot.get('author', {})
- author_forename = author.get('forename', '') if author else ''
- author_surname = author.get('surname', '') if author else ''
- author_name = html.escape(f"{author_forename} {author_surname}".strip()) if author else 'Unknown'
+ author = snapshot.get("author", {})
+ author_forename = author.get("forename", "") if author else ""
+ author_surname = author.get("surname", "") if author else ""
+ author_name = (
+ html.escape(f"{author_forename} {author_surname}".strip())
+ if author
+ else "Unknown"
+ )
# Extract child information (if any)
- child = snapshot.get('child', {})
- child_forename = child.get('forename', '') if child else ''
- child_name = html.escape(f"{child.get('forename', '')} {child.get('surname', '')}".strip()) if child else ''
+ child = snapshot.get("child", {})
+ child_forename = child.get("forename", "") if child else ""
+ child_name = (
+ html.escape(
+ f"{child.get('forename', '')} {child.get('surname', '')}".strip()
+ )
+ if child
+ else ""
+ )
# Create title in format: "Child Forename by Author Forename Surname"
if child_forename and author_forename:
- title = html.escape(f"{child_forename} by {author_forename} {author_surname}".strip())
+ title = html.escape(
+ f"{child_forename} by {author_forename} {author_surname}".strip()
+ )
else:
title = html.escape(f"Snapshot {snapshot_id}")
# Extract location/activity information
- activity = snapshot.get('activity', {})
- activity_name = html.escape(activity.get('name', '')) if activity else ''
+ activity = snapshot.get("activity", {})
+ activity_name = html.escape(activity.get("name", "")) if activity else ""
# Build HTML
html_content = f"""
@@ -327,12 +358,12 @@ class SnapshotDownloader:
- {f'
π€ Author: {author_name}
' if author_name != 'Unknown' else ''}
- {f'
πΆ Child: {child_name}
' if child_name else ''}
- {f'
π― Activity: {activity_name}
' if activity_name else ''}
+ {f'
π€ Author: {author_name}
' if author_name != "Unknown" else ""}
+ {f'
πΆ Child: {child_name}
' if child_name else ""}
+ {f'
π― Activity: {activity_name}
' if activity_name else ""}
-
{content if content else 'No description provided'}
+
{content if content else "No description provided"}
{await self.format_snapshot_media(snapshot, session)}
@@ -343,112 +374,130 @@ class SnapshotDownloader:
return html_content.strip()
- async def format_snapshot_media(self, snapshot: Dict[str, Any], session: aiohttp.ClientSession) -> str:
+ async def format_snapshot_media(
+ self, snapshot: Dict[str, Any], session: aiohttp.ClientSession
+ ) -> str:
"""Format media attachments for a snapshot."""
media_html = ""
# Check for media (images and other files)
- media = snapshot.get('media', [])
- images = [m for m in media if m.get('type') == 'image']
+ media = snapshot.get("media", [])
+ images = [m for m in media if m.get("type") == "image"]
if images:
media_html += '
\n'
- media_html += '
πΈ Images:
\n'
+ media_html += "
πΈ Images:
\n"
media_html += '
\n'
for image in images:
# Download the image file
local_path = await self.download_media_file(session, image)
- image_name = html.escape(image.get('fileName', 'Image'))
+ image_name = html.escape(image.get("fileName", "Image"))
if local_path:
media_html += f'
\n\n'
+ media_html += "\n\n"
# Check for non-image media as attachments
- attachments = [m for m in media if m.get('type') != 'image']
+ attachments = [m for m in media if m.get("type") != "image"]
if attachments:
media_html += '
\n'
- media_html += '
π Attachments:
\n'
+ media_html += "
π Attachments:
\n"
media_html += '
\n'
for attachment in attachments:
# Download the attachment file
local_path = await self.download_media_file(session, attachment)
- attachment_name = html.escape(attachment.get('fileName', 'Attachment'))
- attachment_type = attachment.get('mimeType', 'unknown')
+ attachment_name = html.escape(attachment.get("fileName", "Attachment"))
+ attachment_type = attachment.get("mimeType", "unknown")
if local_path:
media_html += f'
\n'
# Add any additional fields that might be interesting
metadata_fields = [
- ('code', 'Code'),
- ('frameworkIndicatorCount', 'Framework Indicators'),
- ('signed', 'Signed Status'),
- ('type', 'Type')
+ ("code", "Code"),
+ ("frameworkIndicatorCount", "Framework Indicators"),
+ ("signed", "Signed Status"),
+ ("type", "Type"),
]
for field, label in metadata_fields:
value = snapshot.get(field)
if value:
if isinstance(value, list):
- value = ', '.join(str(v) for v in value)
+ value = ", ".join(str(v) for v in value)
metadata_html += f'
\n'
- metadata_html += f' {label}: {html.escape(str(value))}\n'
- metadata_html += f'