问:
Change 'str_date' into time stamp format
I've been working some task to change format from dataframe. My target is to change 'str_date' into time stamp format ("%Y-%m-%d %H-%M-%S").

This is my code:

```<code>def e1t(df):
    result_df = pd.DataFrame()

    def aggregate_function(sub_df):
        grouped_df = {}

        grouped_df['promo_details'] = {
            'code': sub_df['code_promo'].iloc[0],
            'exp_date': sub_df['exp_date_promo'].iloc[0],
            'str_date': sub_df['str_date_promo'].iloc[0],
            'min_price': sub_df['min_price_promo'].iloc[0],
            'max_discount': sub_df['max_discount_promo'].iloc[0],
            'active': sub_df['active_promo'].iloc[0],
            'value': sub_df['value_promo'].iloc[0],
            'promo_type': sub_df['promo_type_promo'].iloc[0],
            'createdAt': sub_df['createdAt_promo'].iloc[0],
            'updatedAt': sub_df['updatedAt_promo'].iloc[0],
        }
</code>```

I have been trying to write the function that will change the date format on 'str_date' into timestamp.

```<code>def e1t(df):
    result_df = pd.DataFrame()

    def aggregate_function(sub_df):
        grouped_df = {}

        #changing the date time column to have timestamp format
        def clean_promo_date(before):
            if type(before) == str:
                return before
            else:
               before.strftime("%Y-%m-%d %H-%M-%S")

        grouped_df['promo_details'] = {
            'code': sub_df['code_promo'].iloc[0],
            'exp_date': sub_df['exp_date_promo'].iloc[0],
            'str_date': clean_promo_date(sub_df['str_date_promo'].iloc[0]),
            'min_price': sub_df['min_price_promo'].iloc[0],
            'max_discount': sub_df['max_discount_promo'].iloc[0],
            'active': sub_df['active_promo'].iloc[0],
            'value': sub_df['value_promo'].iloc[0],
            'promo_type': sub_df['promo_type_promo'].iloc[0],
            'createdAt': sub_df['createdAt_promo'].iloc[0],
            'updatedAt': sub_df['updatedAt_promo'].iloc[0],
        }
</code>```

But got an error

File "main.py", line 108, in aggregate_function
'str_date': sub_df['str_date_promo'].iloc[0].apply(clean_promo_date),
AttributeError: 'str' object has no attribute 'apply'

Is there any ways to apply function for the specific column in the data frame?
How do I choose specific column from the dataframe above? I got the idea to make it into object and apply the function
Thank you

Body:
I've been working some task to change format from dataframe. My target is to change 'str_date' into time stamp format ("%Y-%m-%d %H-%M-%S").

This is my code:

def e1t(df):
    result_df = pd.DataFrame()

    def aggregate_function(sub_df):
        grouped_df = {}

        grouped_df['promo_details'] = {
            'code': sub_df['code_promo'].iloc[0],
            'exp_date': sub_df['exp_date_promo'].iloc[0],
            'str_date': sub_df['str_date_promo'].iloc[0],
            'min_price': sub_df['min_price_promo'].iloc[0],
            'max_discount': sub_df['max_discount_promo'].iloc[0],
            'active': sub_df['active_promo'].iloc[0],
            'value': sub_df['value_promo'].iloc[0],
            'promo_type': sub_df['promo_type_promo'].iloc[0],
            'createdAt': sub_df['createdAt_promo'].iloc[0],
            'updatedAt': sub_df['updatedAt_promo'].iloc[0],
        }

I have been trying to write the function that will change the date format on 'str_date' into timestamp.

def e1t(df):
    result_df = pd.DataFrame()

    def aggregate_function(sub_df):
        grouped_df = {}

        #changing the date time column to have timestamp format
        def clean_promo_date(before):
            if type(before) == str:
                return before
            else:
               before.strftime("%Y-%m-%d %H-%M-%S")

        grouped_df['promo_details'] = {
            'code': sub_df['code_promo'].iloc[0],
            'exp_date': sub_df['exp_date_promo'].iloc[0],
            'str_date': clean_promo_date(sub_df['str_date_promo'].iloc[0]),
            'min_price': sub_df['min_price_promo'].iloc[0],
            'max_discount': sub_df['max_discount_promo'].iloc[0],
            'active': sub_df['active_promo'].iloc[0],
            'value': sub_df['value_promo'].iloc[0],
            'promo_type': sub_df['promo_type_promo'].iloc[0],
            'createdAt': sub_df['createdAt_promo'].iloc[0],
            'updatedAt': sub_df['updatedAt_promo'].iloc[0],
        }

But got an error

File "main.py", line 108, in aggregate_function
'str_date': sub_df['str_date_promo'].iloc[0].apply(clean_promo_date),
AttributeError: 'str' object has no attribute 'apply'

Is there any ways to apply function for the specific column in the data frame?
How do I choose specific column from the dataframe above? I got the idea to make it into object and apply the function
Thank you


来源: stackexchange

问:
Ambiguous self relation detected
```<code>enum UserRole {
  GUEST
  ADMIN
  INSTRUCTOR
  EMPLOYEE
  STUDENT
}

model User {
  id             String       @id @unique @default(cuid())
  createdAt      DateTime?    @default(now())
  updatedAt      DateTime?    @updatedAt
  deletedAt      DateTime?
  firstName      String?
  lastName       String?
  email          String?      @unique
  password       String?
  emailVerified  DateTime?
  photo          String?
  address        String?
  phoneNumber    Int?
  country        String?
  birthOfDate    DateTime?
  role           UserRole     @default(GUEST)
  jobTitle       String?
  hireDate       DateTime?
  Class          Class[]
  enrollmentID   String?      @unique
  enrollmentDate DateTime?
  Attendance     Attendance[]
  Instructors    User[]
  Students       User[]
  Department     Department?  @relation(fields: [departmentId], references: [id])
  departmentId   String?
  Account        Account[]
  Session        Session[]
}

model Department {
  id        String  @id @unique @default(cuid())
  name      String? @unique
  Employees User[]
}

model Class {
  id          String       @id @unique @default(cuid())
  name        String?      @unique
  startDate   DateTime?
  Instructors User[]
  Students    User[]
  Attendance  Attendance[]
}

model Attendance {
  id          String    @id @unique @default(cuid())
  date        DateTime?
  Instructors User[]
  Students    User[]
  Class       Class?    @relation(fields: [classId], references: [id])
  classId     String?
}
</code>```

I'm getting error when I try to connect User table with Department, Class, Attendance tables.

```<code>Error validating model "User": Ambiguous self relation detected. The fields `Instructors` and `Students` in model `User` both refer to `User`. If they are part of the same relation add the same relation name for them with `@relation(<name>)`.
</code>```

I want to create different departments with employees, and different classes with instructors and students based on User table. A User with Admin role must track students' and instructors' attendance.

ContentLicense: CC BY-SA 4.0

Title: Ambiguous self relation detected

Body:
enum UserRole {
  GUEST
  ADMIN
  INSTRUCTOR
  EMPLOYEE
  STUDENT
}

model User {
  id             String       @id @unique @default(cuid())
  createdAt      DateTime?    @default(now())
  updatedAt      DateTime?    @updatedAt
  deletedAt      DateTime?
  firstName      String?
  lastName       String?
  email          String?      @unique
  password       String?
  emailVerified  DateTime?
  photo          String?
  address        String?
  phoneNumber    Int?
  country        String?
  birthOfDate    DateTime?
  role           UserRole     @default(GUEST)
  jobTitle       String?
  hireDate       DateTime?
  Class          Class[]
  enrollmentID   String?      @unique
  enrollmentDate DateTime?
  Attendance     Attendance[]
  Instructors    User[]
  Students       User[]
  Department     Department?  @relation(fields: [departmentId], references: [id])
  departmentId   String?
  Account        Account[]
  Session        Session[]
}

model Department {
  id        String  @id @unique @default(cuid())
  name      String? @unique
  Employees User[]
}

model Class {
  id          String       @id @unique @default(cuid())
  name        String?      @unique
  startDate   DateTime?
  Instructors User[]
  Students    User[]
  Attendance  Attendance[]
}

model Attendance {
  id          String    @id @unique @default(cuid())
  date        DateTime?
  Instructors User[]
  Students    User[]
  Class       Class?    @relation(fields: [classId], references: [id])
  classId     String?
}

I'm getting error when I try to connect User table with Department, Class, Attendance tables.

Error validating model "User": Ambiguous self relation detected. The fields `Instructors` and `Students` in model `User` both refer to `User`. If they are part of the same relation add the same relation name for them with `@relation(<name>)`.

I want to create different departments with employees, and different classes with instructors and students based on User table. A User with Admin role must track students' and instructors' attendance.


问:
Ioinic React: Oauth with google or facebook
I'm trying to add a login with facebook or google in my Capacitor React but all of the frameworks are documented in Angular. Is there a way to add this feature on an Ionic React App

I tried using the web version and it just redirects away from the app.


问:
Not getting the value from shared preference
I am trying to insert a notification type in SharedPreferences which I receive in onMessageReceived as a body part when it gets a notification. And I fetch the value of the notification type on the splash screen after tapping the notification. But I am not able to get it, as the value is always empty.

```<code>SharedPreferences preferences = getSharedPreferences(Constants.Preferences.PreferencesName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();

if (notificationType != null && notificationType.equalsIgnoreCase("chatmessage")) {
    Log.d(TAG, "sendNotification: " + notificationType);
    Intent intent = new Intent(this, SplashScreenActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    editor.putString("notificationType", notificationType);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    String title = messageBody.get("title");
    String message = messageBody.get("message");
    String channelId = "patient_channel";

    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.mipmap.ic_patient_logo)
            .setContentTitle(title)
            .setContentText(message)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
    // bigTextStyle.setBigContentTitle(title);
    bigTextStyle.bigText(message);

    notificationBuilder.setStyle(bigTextStyle);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());
}

editor.apply();
</code>```

Body:
I am trying to insert a notification type in SharedPreferences which I receive in onMessageReceived as a body part when it gets a notification. And I fetch the value of the notification type on the splash screen after tapping the notification. But I am not able to get it, as the value is always empty.

SharedPreferences preferences = getSharedPreferences(Constants.Preferences.PreferencesName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();

if (notificationType != null && notificationType.equalsIgnoreCase("chatmessage")) {
    Log.d(TAG, "sendNotification: " + notificationType);
    Intent intent = new Intent(this, SplashScreenActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    editor.putString("notificationType", notificationType);

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    String title = messageBody.get("title");
    String message = messageBody.get("message");
    String channelId = "patient_channel";

    Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.mipmap.ic_patient_logo)
            .setContentTitle(title)
            .setContentText(message)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);

    NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
    // bigTextStyle.setBigContentTitle(title);
    bigTextStyle.bigText(message);

    notificationBuilder.setStyle(bigTextStyle);

    NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notificationManager.notify(0, notificationBuilder.build());
}

editor.apply();


问:
S3 change last modified date
I have an S3 bucket that sends event notifications for new objects to SQS. Event notifications are filtered to one folder.
I want to simulate an upload of a large number of files at the same time. The problem is I need to upload faster. The fastest I got was to upload to another folder in the same s3 bucket and move the folder into the one with the trigger. It still copies files one by one.
Another thing I tried is:

disable event notification

copy files into the target folder

enable event notification

copy each file into itself (which causes the last modified date change and triggers an event notification)

Is there something faster? Or can we change the last modified date and trigger an event notification without copying?

I'm aware I can generate SQS events programmatically, but I want to do some real testing.

Title: S3 change last modified date


问:
group by three variables in very large data frame
I have a very large data frame in r with 4.3 million rows and 7 columns which I need to group and summarize in order to create some graphics (with ggplot) later on. But it seems that this isn't working, I waited for a couple hours, but nothing happend.

I have an example with a small data frame that works:

```<code>SDO_ID <- c(44, 44, 44, 44, 45, 45, 45, 45)
Value <- c(93,94,88,77,68,51,55,78)
zeitstempel <- c("2018-01-01 01:00:00", "2018-01-01 02:00:00", "2018-01-02 01:00:00", "2018-01-02 02:00:00")
time <- format(as.POSIXct(zeitstempel),format = "%H:%M:%S")
date <- as.Date(zeitstempel)
df <- data.frame(SDO_ID, Value, time, date)

rf_by_day <- df %>% group_by(date, SDO_ID) %>%
  summarize(value = mean(Value))
</code>```

This example works as expected. But with my original data frame (over 4.3 million rows) I don't get any result. Do I just have to wait longer? Or is there anything that I could do to improve the code?

Would it help if I first extract the months and then use the months for grouping instead of the exact date (since there will be fewer rows in the final data frame)? Or does this not make any difference, since the original data frame has 4.3 million rows anyways?

Thank you!

Body:
I have a very large data frame in r with 4.3 million rows and 7 columns which I need to group and summarize in order to create some graphics (with ggplot) later on. But it seems that this isn't working, I waited for a couple hours, but nothing happend.

I have an example with a small data frame that works:

SDO_ID <- c(44, 44, 44, 44, 45, 45, 45, 45)
Value <- c(93,94,88,77,68,51,55,78)
zeitstempel <- c("2018-01-01 01:00:00", "2018-01-01 02:00:00", "2018-01-02 01:00:00", "2018-01-02 02:00:00")
time <- format(as.POSIXct(zeitstempel),format = "%H:%M:%S")
date <- as.Date(zeitstempel)
df <- data.frame(SDO_ID, Value, time, date)

rf_by_day <- df %>% group_by(date, SDO_ID) %>%
  summarize(value = mean(Value))

This example works as expected. But with my original data frame (over 4.3 million rows) I don't get any result. Do I just have to wait longer? Or is there anything that I could do to improve the code?

Would it help if I first extract the months and then use the months for grouping instead of the exact date (since there will be fewer rows in the final data frame)? Or does this not make any difference, since the original data frame has 4.3 million rows anyways?

Thank you!


问:
Using async and findOne for mongoDB takes decades to connect
I want to use the async to verify whether the user is registered so it can access the app when the user tries to log in. This code doesn't give any error, but it takes decades to search from the database, and in the end, I've never seen it connected.

Any suggestion to fix this and make it faster? I think I'm mistaken in the code I wrote because something ain't right.

```<code>const usersCollection = require('../db').collection("users");

User.prototype.login = () =>{
async function run() {
    try {
        const attemptedUser = await usersCollection.findOne({ name: this.data.username });
        if (attemptedUser && attemptedUser.password == this.data.password) {
            console.log("congrats");
        } else if (attemptedUser && attemptedUser.password !== this.data.password) {
            throw new Error("Access Denied");
        }
    } catch (err) {
        console.log(err.message);
    }
}}
</code>```

Body:
I want to use the async to verify whether the user is registered so it can access the app when the user tries to log in. This code doesn't give any error, but it takes decades to search from the database, and in the end, I've never seen it connected.

Any suggestion to fix this and make it faster? I think I'm mistaken in the code I wrote because something ain't right.

const usersCollection = require('../db').collection("users");

User.prototype.login = () =>{
async function run() {
    try {
        const attemptedUser = await usersCollection.findOne({ name: this.data.username });
        if (attemptedUser && attemptedUser.password == this.data.password) {
            console.log("congrats");
        } else if (attemptedUser && attemptedUser.password !== this.data.password) {
            throw new Error("Access Denied");
        }
    } catch (err) {
        console.log(err.message);
    }
}}


问:
Wifimanager 8266 move to esp32 always connected. Disconnects or drops connection
I have a project on a Wemos d1 mini.  I am using  the WiFi manager and for the most part works fine.

I have 2 issues I’m trying to fix:

I’m trying to move all the code to lolin esp d32.  But the WiFi  manager broadcasts the station only for a minute and then if I needed to connect to it I have to reset the board. Can someone help me resolve this issue so it works like I had it on the d1

when it was on the d1 it would disconnect or lose connection. Then I would have to tee tee the credentials again if it failed to connect after so many tries

I want to move the code to an ESP32 and fix these issues.  I need to have a solid, reliable connection with the WiFi.

A) possibly solve this disconnection issue possibly with a line of code for high power mode?

B) make a code that checks if it is still connects if not to reconnect t rather than send it back to the cridential page so basically solve the down time by some logic that will maintain the always connected situation.

C) I want to add a line of code to have an indicator light turn on if it can’t connect or loses connection and turns off when there is a connection.

Here is what I have so far for the main.cpp

```<code>#include <WiFiManager.h>
void setup() {
  Serial.begin(115200);
  Files.start();
  Lights.begin();
  UI.begin();
  Auth.begin();
  COM.begin();
  Serial.print(F("\n\n====================<<<<<<<<  WiFi Manager  >>>>>>=====================\n\n"));
  factoryTest();
  Serial.println(FW_VERSION);

#ifdef COLORCODE
  Lights.alertStatus = ALERT_BOOTUP;
  Lights.alert();
#endif

  WiFiManager wifiManager;
  //wifiManager.setConfigPortalBlocking(false);
  wifiManager.autoConnect("Goal Light");

  //while (WiFi.status() != WL_CONNECTED) {
#ifdef COLORCODE
  Lights.alertStatus = ALERT_WIFI;
  if (wifiManager.getWiFiIsSaved()) {
    Network.loop();
  }
  Lights.loop();
#endif
  //wifiManager.process();
  //}

  Lights.alertStatus = ALERT_ERROR;
  Lights.status = LIGHT_PAUSED;
  Files.update();
  if (Files.check("/user.txt") && Files.check("/password.txt")) {
    Updater OTA;
  }
  Auth.authenticate();

  UI.buildWeb();
}

int period = 1500;
unsigned long time_now = 0;
void loop() {
  if (millis() - time_now > period) {
    time_now = millis();
  }
  Sport.loop();
  UI.wss->loop();
  dnsServer.processNextRequest();
  server.handleClient();
  SB.loop();
  Lights.loop();

#ifdef COLORCODE
  Network.loop();
#endif
}
</code>```

I have platformio that it was made on.

When I move it to my esp32 code I’m getting error for things Im not sure how to fix .

Body:
I have a project on a Wemos d1 mini.  I am using  the WiFi manager and for the most part works fine.

I have 2 issues I’m trying to fix:

I’m trying to move all the code to lolin esp d32.  But the WiFi  manager broadcasts the station only for a minute and then if I needed to connect to it I have to reset the board. Can someone help me resolve this issue so it works like I had it on the d1

when it was on the d1 it would disconnect or lose connection. Then I would have to tee tee the credentials again if it failed to connect after so many tries

I want to move the code to an ESP32 and fix these issues.  I need to have a solid, reliable connection with the WiFi.

A) possibly solve this disconnection issue possibly with a line of code for high power mode?

B) make a code that checks if it is still connects if not to reconnect t rather than send it back to the cridential page so basically solve the down time by some logic that will maintain the always connected situation.

C) I want to add a line of code to have an indicator light turn on if it can’t connect or loses connection and turns off when there is a connection.

Here is what I have so far for the main.cpp

#include <WiFiManager.h>
void setup() {
  Serial.begin(115200);
  Files.start();
  Lights.begin();
  UI.begin();
  Auth.begin();
  COM.begin();
  Serial.print(F("\n\n====================<<<<<<<<  WiFi Manager  >>>>>>=====================\n\n"));
  factoryTest();
  Serial.println(FW_VERSION);

#ifdef COLORCODE
  Lights.alertStatus = ALERT_BOOTUP;
  Lights.alert();
#endif

  WiFiManager wifiManager;
  //wifiManager.setConfigPortalBlocking(false);
  wifiManager.autoConnect("Goal Light");

  //while (WiFi.status() != WL_CONNECTED) {
#ifdef COLORCODE
  Lights.alertStatus = ALERT_WIFI;
  if (wifiManager.getWiFiIsSaved()) {
    Network.loop();
  }
  Lights.loop();
#endif
  //wifiManager.process();
  //}

  Lights.alertStatus = ALERT_ERROR;
  Lights.status = LIGHT_PAUSED;
  Files.update();
  if (Files.check("/user.txt") && Files.check("/password.txt")) {
    Updater OTA;
  }
  Auth.authenticate();

  UI.buildWeb();
}

int period = 1500;
unsigned long time_now = 0;
void loop() {
  if (millis() - time_now > period) {
    time_now = millis();
  }
  Sport.loop();
  UI.wss->loop();
  dnsServer.processNextRequest();
  server.handleClient();
  SB.loop();
  Lights.loop();

#ifdef COLORCODE
  Network.loop();
#endif
}

I have platformio that it was made on.

When I move it to my esp32 code I’m getting error for things Im not sure how to fix .


问:
add interactivity to ggplot - having issues with plotly, ggiraph
I have a faceted ggplot, and I'm really struggling to add a tooltip on hover.

A sample file is here: https://github.com/rollingstone09/help (edit: have now added a dput output to the bottom of this post).

```<code>a <- read_excel("a.xlsx")
a$Date <- as.Date(as.character(a$Date))
a$Week <- as.Date(as.character(a$Week))
a$Day <- factor(a$Day,
                 levels = c("Monday", "Tuesday",
                            "Wednesday", "Thursday",
                            "Friday", "Saturday", "Sunday"))

a$Session <- factor(a$Session,
                     levels = c("PM", "AM",
                                "All Day"))

a$Priority <- as.character(as.character(a$Priority))

 aa2 <- a %>%
   group_by(Date, Theatre) %>%
   mutate(Order3 = row_number())

aa2 %>%
   ggplot() +
   geom_bar(aes("", Available), stat = "identity", position = "identity", colour = "red", fill = "white", alpha = 0, linetype = 2) +
   geom_col(aes("", Booked, fill = Priority), colour = "black") +
   geom_point(aes("", Available), size = 1, colour = "red", shape = 4, stroke = 2) +
   coord_flip() +
   facet_grid(Theatre~Day) +
   theme_bw()
</code>```

I would like to be able to hover over the stacked bars, and the following information (from "a") to pop up: "PID", "Booked", "Operation", "Surgeon", "Ward To". My hope is to add a copy of the plot to a rmarkdown report, and ideally the end product would be a clone of the above ggplot but with this information shown on hover.

If I try to use ggplotly: the plot looks awful... the ggplot theme_bw() is overwritten, geom_bar disappears, my geom_point is no longer a cross etc.. If I try to use ggiraph, the plot seems to quadruple in size, the facets become squashed. I have tried googling how I can go about rectifying, but I'm at a loss and just hoping someone can either show me or point me in the right direction of where I'd need to go to learn. Any help greatly appreciated.

(Added dput output of my sample table as requested) --

```<code>structure(list(Date = structure(c(1672790400, 1672790400, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672876800, 1672876800,
1672876800, 1672963200, 1672963200, 1672963200, 1672963200, 1672704000,
1672704000, 1672704000, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672790400, 1672790400, 1672876800,
1672876800, 1672876800, 1672876800, 1672876800, 1672704000, 1672790400,
1672963200, 1672704000, 1672876800, 1672876800, 1672876800, 1672876800,
1672704000, 1672704000, 1672704000, 1672704000, 1672876800, 1672876800,
1672876800, 1672876800, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672790400, 1672790400, 1672790400,
1672963200, 1672963200, 1672963200, 1672790400, 1672790400, 1672790400,
1672790400, 1672876800, 1672876800, 1672963200, 1672963200, 1672790400,
1672790400, 1672790400, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672876800, 1672876800, 1672963200,
1672963200, 1672876800, 1672876800, 1672790400, 1672790400, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672876800, 1672876800,
1672876800, 1672704000, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672704000, 1672790400, 1672876800, 1672876800, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672963200, 1672963200,
1672963200, 1672963200, 1672963200, 1672963200, 1672963200, 1672963200,
1672876800, 1672876800, 1672876800, 1672963200, 1672963200, 1672963200,
1672963200, 1673049600, 1672790400, 1672876800, 1672876800, 1672876800,
1672876800, 1672704000), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
    Week = structure(c(1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
    SID = c(686724, 686724, 686724, 686724, 686724, 686726, 686726,
    686726, 686726, 686726, 686728, 686728, 686728, 686728, 686732,
    686732, 686732, 686732, 686732, 686732, 686732, 686732, 686734,
    686734, 686734, 686734, 686736, 686736, 686736, 686736, 686736,
    686744, 686746, 686752, 686756, 686760, 686760, 686760, 686760,
    686768, 686768, 686770, 686770, 686774, 686774, 686774, 686776,
    686782, 686782, 686782, 686782, 686782, 686784, 686784, 686784,
    686786, 686786, 686790, 686792, 686792, 686800, 686800, 686800,
    686800, 686802, 686802, 686804, 686804, 686808, 686810, 686810,
    686816, 686816, 686816, 686826, 686826, 686828, 686828, 686830,
    686830, 686832, 686832, 686948, 686948, 686954, 686954, 686956,
    686956, 686956, 686958, 686958, 686960, 686960, 686960, 686962,
    686962, 686962, 686964, 686964, 686964, 687114, 687116, 687118,
    687118, 687166, 687166, 687166, 687168, 687168, 687170, 687380,
    687380, 687382, 687382, 687382, 687382, 687382, 688596, 688596,
    688596, 688804, 688804, 688806, 688806, 688814, 688828, 689432,
    689432, 689434, 689434, 689522), PID = c("ANON1", "ANON2",
    "ANON3", "ANON4", "ANON5", "ANON6", "ANON7", "ANON8", "ANON9",
    "ANON10", "ANON11", "ANON12", "ANON13", "ANON14", "ANON15",
    "ANON16", "ANON17", "ANON18", "ANON19", "ANON20", "ANON21",
    "ANON22", "ANON23", "ANON24", "ANON25", "ANON26", "ANON27",
    "ANON28", "ANON29", "ANON30", "ANON31", "ANON32", "ANON33",
    "ANON34", "ANON35", "ANON36", "ANON37", "ANON38", "ANON39",
    "ANON40", "ANON41", "ANON42", "ANON43", "ANON44", "ANON45",
    "ANON46", "ANON47", "ANON48", "ANON49", "ANON50", "ANON51",
    "ANON52", "ANON53", "ANON54", "ANON55", "ANON56", "ANON57",
    "ANON58", "ANON59", "ANON60", "ANON61", "ANON62", "ANON63",
    "ANON64", "ANON65", "ANON66", "ANON67", "ANON68", "ANON69",
    "ANON70", "ANON71", "ANON72", "ANON73", "ANON74", "ANON75",
    "ANON76", "ANON77", "ANON78", "ANON79", "ANON80", "ANON81",
    "ANON82", "ANON83", "ANON84", "ANON85", "ANON86", "ANON87",
    "ANON88", "ANON89", "ANON90", "ANON91", "ANON92", "ANON93",
    "ANON94", "ANON95", "ANON96", "ANON97", "ANON98", "ANON99",
    "ANON100", "ANON101", "ANON102", "ANON103", "ANON104", "ANON105",
    "ANON106", "ANON107", "ANON108", "ANON109", "ANON110", "ANON111",
    "ANON112", "ANON113", "ANON114", "ANON115", "ANON116", "ANON117",
    "ANON118", "ANON119", "ANON120", "ANON121", "ANON122", "ANON123",
    "ANON124", "ANON125", "ANON126", "ANON127", "ANON128", "ANON129",
    "ANON130", "ANON131"), Day = c("Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Wednesday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Thursday", "Friday", "Friday", "Friday",
    "Friday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Tuesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Thursday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Wednesday", "Friday",
    "Tuesday", "Thursday", "Thursday", "Thursday", "Thursday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Wednesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Friday", "Friday", "Friday", "Wednesday",
    "Wednesday", "Wednesday", "Wednesday", "Thursday", "Thursday",
    "Friday", "Friday", "Wednesday", "Wednesday", "Wednesday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Wednesday",
    "Wednesday", "Thursday", "Thursday", "Friday", "Friday",
    "Thursday", "Thursday", "Wednesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Thursday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Wednesday",
    "Thursday", "Thursday", "Wednesday", "Wednesday", "Wednesday",
    "Thursday", "Thursday", "Friday", "Friday", "Friday", "Friday",
    "Friday", "Friday", "Friday", "Friday", "Thursday", "Thursday",
    "Thursday", "Friday", "Friday", "Friday", "Friday", "Saturday",
    "Wednesday", "Thursday", "Thursday", "Thursday", "Thursday",
    "Tuesday"), Operation = c("Text 1", "Text 2", "Text 3", "Text 4",
    "Text 5", "Text 6", "Text 7", "Text 8", "Text 9", "Text 10",
    "Text 11", "Text 12", "Text 13", "Text 14", "Text 15", "Text 16",
    "Text 17", "Text 18", "Text 19", "Text 20", "Text 21", "Text 22",
    "Text 23", "Text 24", "Text 25", "Text 26", "Text 27", "Text 28",
    "Text 29", "Text 30", "Text 31", "Text 32", "Text 33", "Text 34",
    "Text 35", "Text 36", "Text 37", "Text 38", "Text 39", "Text 40",
    "Text 41", "Text 42", "Text 43", "Text 44", "Text 45", "Text 46",
    "Text 47", "Text 48", "Text 49", "Text 50", "Text 51", "Text 52",
    "Text 53", "Text 54", "Text 55", "Text 56", "Text 57", "Text 58",
    "Text 59", "Text 60", "Text 61", "Text 62", "Text 63", "Text 64",
    "Text 65", "Text 66", "Text 67", "Text 68", "Text 69", "Text 70",
    "Text 71", "Text 72", "Text 73", "Text 74", "Text 75", "Text 76",
    "Text 77", "Text 78", "Text 79", "Text 80", "Text 81", "Text 82",
    "Text 83", "Text 84", "Text 85", "Text 86", "Text 87", "Text 88",
    "Text 89", "Text 90", "Text 91", "Text 92", "Text 93", "Text 94",
    "Text 95", "Text 96", "Text 97", "Text 98", "Text 99", "Text 100",
    "Text 101", "Text 102", "Text 103", "Text 104", "Text 105",
    "Text 106", "Text 107", "Text 108", "Text 109", "Text 110",
    "Text 111", "Text 112", "Text 113", "Text 114", "Text 115",
    "Text 116", "Text 117", "Text 118", "Text 119", "Text 120",
    "Text 121", "Text 122", "Text 123", "Text 124", "Text 125",
    "Text 126", "Text 127", "Text 128", "Text 129", "Text 130",
    "Text 131"), Specialty = c("Text 1", "Text 2", "Text 3",
    "Text 4", "Text 5", "Text 6", "Text 7", "Text 8", "Text 9",
    "Text 10", "Text 11", "Text 12", "Text 13", "Text 14", "Text 15",
    "Text 16", "Text 17", "Text 18", "Text 19", "Text 20", "Text 21",
    "Text 22", "Text 23", "Text 24", "Text 25", "Text 26", "Text 27",
    "Text 28", "Text 29", "Text 30", "Text 31", "Text 32", "Text 33",
    "Text 34", "Text 35", "Text 36", "Text 37", "Text 38", "Text 39",
    "Text 40", "Text 41", "Text 42", "Text 43", "Text 44", "Text 45",
    "Text 46", "Text 47", "Text 48", "Text 49", "Text 50", "Text 51",
    "Text 52", "Text 53", "Text 54", "Text 55", "Text 56", "Text 57",
    "Text 58", "Text 59", "Text 60", "Text 61", "Text 62", "Text 63",
    "Text 64", "Text 65", "Text 66", "Text 67", "Text 68", "Text 69",
    "Text 70", "Text 71", "Text 72", "Text 73", "Text 74", "Text 75",
    "Text 76", "Text 77", "Text 78", "Text 79", "Text 80", "Text 81",
    "Text 82", "Text 83", "Text 84", "Text 85", "Text 86", "Text 87",
    "Text 88", "Text 89", "Text 90", "Text 91", "Text 92", "Text 93",
    "Text 94", "Text 95", "Text 96", "Text 97", "Text 98", "Text 99",
    "Text 100", "Text 101", "Text 102", "Text 103", "Text 104",
    "Text 105", "Text 106", "Text 107", "Text 108", "Text 109",
    "Text 110", "Text 111", "Text 112", "Text 113", "Text 114",
    "Text 115", "Text 116", "Text 117", "Text 118", "Text 119",
    "Text 120", "Text 121", "Text 122", "Text 123", "Text 124",
    "Text 125", "Text 126", "Text 127", "Text 128", "Text 129",
    "Text 130", "Text 131"), Booked = c(150, 150, 90, 50, 90,
    90, 75, 180, 120, 75, 120, 90, 60, 120, 90, 90, 45, 45, 45,
    60, 70, 30, 60, 90, 240, 90, 180, 180, 60, 60, 60, 540, 810,
    480, 810, 60, 120, 60, 60, 82, 90, 90, 119, 90, 75, 70, 240,
    60, 150, 60, 90, 90, 105, 60, 110, 90, 75, 240, 120, 90,
    90, 120, 90, 180, 360, 60, 420, 60, 240, 90, 90, 60, 90,
    60, 240, 280, 150, 181, 280, 240, 240, 360, 240, 240, 120,
    120, 75, 90, 90, 120, 60, 60, 75, 75, 90, 90, 60, 60, 60,
    90, 500, 510, 152, 363, 87, 227, 150, 528, 123, 300, 150,
    100, 60, 60, 50, 40, 50, 90, 90, 60, 60, 120, 240, 120, 427,
    540, 240, 90, 240, 60, 240), Available = c(540, 540, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
    540, 540, 540, 540, 540, 810, 540, 810, 540, 540, 540, 540,
    240, 240, 240, 240, 240, 240, 240, 240, 540, 540, 540, 540,
    540, 240, 240, 240, 240, 240, 240, 240, 240, 540, 540, 540,
    540, 540, 540, 540, 540, 240, 240, 240, 240, 240, 240, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 240, 240, 240,
    240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
    240, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 240,
    240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
    240, 240, 540, 240, 240, 240, 240, 240), Theatre = c("03",
    "03", "03", "03", "03", "03", "03", "03", "03", "03", "03",
    "03", "03", "03", "04", "04", "04", "04", "04", "04", "04",
    "04", "04", "04", "04", "04", "04", "04", "04", "04", "04",
    "05", "05", "05", "06", "06", "06", "06", "06", "07", "07",
    "07", "07", "07", "07", "07", "07", "08", "08", "08", "08",
    "08", "08", "08", "08", "08", "08", "08", "08", "08", "09",
    "09", "09", "09", "09", "09", "09", "09", "10", "10", "10",
    "11", "11", "11", "12", "12", "12", "12", "12", "12", "12",
    "12", "05", "05", "07", "07", "07", "07", "07", "08", "08",
    "08", "08", "08", "09", "09", "09", "09", "09", "09", "14",
    "14", "14", "14", "15", "15", "15", "15", "15", "15", "04",
    "04", "04", "04", "04", "04", "04", "11", "11", "11", "06",
    "06", "06", "06", "15", "06", "10", "10", "10", "10", "03"
    ), Priority = c(3, 3, 2, 1, 1, 1, 2, 1, 4, 2, 4, 4, 2, 3,
    2, 4, 2, 1, 2, 3, 2, 2, 3, 1, 4, 1, 1, 1, 2, 3, 2, 3, 1,
    4, 4, 3, 4, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 4, 1, 4, 2, 4,
    2, 1, 1, 4, 3, 3, 2, 2, 4, 4, 2, 1, 2, 4, 3, 4, 4, 1, 4,
    4, 3, 1, 3, 1, 4, 4, 2, 4, 3, 1, 1, 4, 1, 1, 2, 2, 3, 1,
    3, 4, 4, 4, 4, 1, 4, 4, 2, 4, 2, 3, 3, 1, 3, 2, 1, 3, 4,
    1, 4, 4, 1, 1, 3, 4, 2, 1, 4, 2, 3, 2, 3, 4, 2, 4, 1, 1,
    1, 1, 3), Session = c("All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "AM",
    "AM", "PM", "PM", "AM", "AM", "AM", "PM", "All Day", "All Day",
    "All Day", "All Day", "All Day", "AM", "AM", "AM", "PM",
    "PM", "AM", "PM", "PM", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "AM",
    "PM", "PM", "PM", "PM", "PM", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "AM", "AM", "PM", "PM", "PM", "AM", "AM", "PM",
    "PM", "PM", "AM", "AM", "AM", "PM", "PM", "PM", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "AM", "AM", "PM", "PM",
    "PM", "PM", "PM", "PM", "PM", "PM", "AM", "AM", "PM", "PM",
    "AM", "All Day", "AM", "AM", "PM", "PM", "AM"), WardTo = c(40,
    15, 5, 33, 11, 18, 40, 19, 12, 34, 41, 24, 9, 23, 36, 26,
    25, 31, 46, 30, 12, 4, 27, 32, 48, 46, 3, 23, 44, 1, 35,
    45, 9, 34, 21, 28, 26, 23, 20, 37, 39, 2, 42, 36, 35, 6,
    36, 6, 11, 39, 13, 12, 28, 50, 47, 16, 26, 2, 33, 38, 50,
    47, 49, 10, 7, 49, 36, 44, 42, 2, 38, 19, 43, 21, 12, 10,
    48, 10, 14, 42, 2, 39, 11, 41, 18, 41, 47, 15, 39, 8, 11,
    17, 11, 12, 12, 20, 50, 12, 2, 46, 13, 6, 4, 22, 8, 3, 11,
    27, 12, 12, 14, 27, 23, 48, 25, 49, 49, 30, 1, 28, 35, 9,
    37, 21, 27, 25, 31, 18, 13, 3, 7), Order = c(1, 2, 3, 4,
    5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 1,
    2, 3, 4, 1, 2, 3, 4, 5, 1, 1, 1, 1, 1, 2, 3, 4, 1, 2, 1,
    2, 1, 2, 3, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 1, 1, 2, 1,
    2, 3, 4, 1, 2, 1, 2, 1, 1, 2, 1, 2, 3, 1, 2, 1, 2, 1, 2,
    1, 2, 1, 2, 1, 2, 1, 2, 3, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2,
    3, 1, 1, 1, 2, 1, 2, 3, 1, 2, 1, 1, 2, 1, 2, 3, 4, 5, 1,
    2, 3, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1), Surgeon = c(2, 2,
    5, 4, 9, 4, 8, 4, 5, 7, 9, 7, 8, 8, 10, 6, 6, 1, 2, 1, 4,
    5, 7, 4, 9, 4, 6, 10, 1, 3, 10, 4, 8, 9, 4, 3, 2, 7, 6, 5,
    1, 5, 10, 8, 5, 8, 10, 4, 10, 4, 3, 4, 7, 8, 5, 9, 8, 1,
    5, 10, 3, 1, 3, 6, 10, 7, 8, 3, 5, 1, 2, 6, 5, 9, 10, 4,
    9, 2, 4, 10, 5, 7, 2, 6, 8, 3, 9, 2, 4, 1, 9, 9, 2, 3, 9,
    8, 9, 6, 10, 5, 7, 9, 2, 5, 7, 2, 10, 2, 2, 1, 1, 2, 6, 5,
    3, 10, 2, 4, 3, 3, 3, 9, 9, 7, 1, 6, 3, 5, 5, 10, 2)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -131L))
</code>```

Body:
I have a faceted ggplot, and I'm really struggling to add a tooltip on hover.

A sample file is here: https://github.com/rollingstone09/help (edit: have now added a dput output to the bottom of this post).

a <- read_excel("a.xlsx")
a$Date <- as.Date(as.character(a$Date))
a$Week <- as.Date(as.character(a$Week))
a$Day <- factor(a$Day,
                 levels = c("Monday", "Tuesday",
                            "Wednesday", "Thursday",
                            "Friday", "Saturday", "Sunday"))

a$Session <- factor(a$Session,
                     levels = c("PM", "AM",
                                "All Day"))

a$Priority <- as.character(as.character(a$Priority))

 aa2 <- a %>%
   group_by(Date, Theatre) %>%
   mutate(Order3 = row_number())

aa2 %>%
   ggplot() +
   geom_bar(aes("", Available), stat = "identity", position = "identity", colour = "red", fill = "white", alpha = 0, linetype = 2) +
   geom_col(aes("", Booked, fill = Priority), colour = "black") +
   geom_point(aes("", Available), size = 1, colour = "red", shape = 4, stroke = 2) +
   coord_flip() +
   facet_grid(Theatre~Day) +
   theme_bw()

I would like to be able to hover over the stacked bars, and the following information (from "a") to pop up: "PID", "Booked", "Operation", "Surgeon", "Ward To". My hope is to add a copy of the plot to a rmarkdown report, and ideally the end product would be a clone of the above ggplot but with this information shown on hover.

If I try to use ggplotly: the plot looks awful... the ggplot theme_bw() is overwritten, geom_bar disappears, my geom_point is no longer a cross etc.. If I try to use ggiraph, the plot seems to quadruple in size, the facets become squashed. I have tried googling how I can go about rectifying, but I'm at a loss and just hoping someone can either show me or point me in the right direction of where I'd need to go to learn. Any help greatly appreciated.

(Added dput output of my sample table as requested) --

structure(list(Date = structure(c(1672790400, 1672790400, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672876800, 1672876800,
1672876800, 1672963200, 1672963200, 1672963200, 1672963200, 1672704000,
1672704000, 1672704000, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672790400, 1672790400, 1672876800,
1672876800, 1672876800, 1672876800, 1672876800, 1672704000, 1672790400,
1672963200, 1672704000, 1672876800, 1672876800, 1672876800, 1672876800,
1672704000, 1672704000, 1672704000, 1672704000, 1672876800, 1672876800,
1672876800, 1672876800, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672790400, 1672790400, 1672790400,
1672963200, 1672963200, 1672963200, 1672790400, 1672790400, 1672790400,
1672790400, 1672876800, 1672876800, 1672963200, 1672963200, 1672790400,
1672790400, 1672790400, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672790400, 1672790400, 1672876800, 1672876800, 1672963200,
1672963200, 1672876800, 1672876800, 1672790400, 1672790400, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672876800, 1672876800,
1672876800, 1672704000, 1672704000, 1672704000, 1672704000, 1672704000,
1672704000, 1672704000, 1672790400, 1672876800, 1672876800, 1672790400,
1672790400, 1672790400, 1672876800, 1672876800, 1672963200, 1672963200,
1672963200, 1672963200, 1672963200, 1672963200, 1672963200, 1672963200,
1672876800, 1672876800, 1672876800, 1672963200, 1672963200, 1672963200,
1672963200, 1673049600, 1672790400, 1672876800, 1672876800, 1672876800,
1672876800, 1672704000), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
    Week = structure(c(1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600, 1672617600, 1672617600, 1672617600,
    1672617600, 1672617600), class = c("POSIXct", "POSIXt"), tzone = "UTC"),
    SID = c(686724, 686724, 686724, 686724, 686724, 686726, 686726,
    686726, 686726, 686726, 686728, 686728, 686728, 686728, 686732,
    686732, 686732, 686732, 686732, 686732, 686732, 686732, 686734,
    686734, 686734, 686734, 686736, 686736, 686736, 686736, 686736,
    686744, 686746, 686752, 686756, 686760, 686760, 686760, 686760,
    686768, 686768, 686770, 686770, 686774, 686774, 686774, 686776,
    686782, 686782, 686782, 686782, 686782, 686784, 686784, 686784,
    686786, 686786, 686790, 686792, 686792, 686800, 686800, 686800,
    686800, 686802, 686802, 686804, 686804, 686808, 686810, 686810,
    686816, 686816, 686816, 686826, 686826, 686828, 686828, 686830,
    686830, 686832, 686832, 686948, 686948, 686954, 686954, 686956,
    686956, 686956, 686958, 686958, 686960, 686960, 686960, 686962,
    686962, 686962, 686964, 686964, 686964, 687114, 687116, 687118,
    687118, 687166, 687166, 687166, 687168, 687168, 687170, 687380,
    687380, 687382, 687382, 687382, 687382, 687382, 688596, 688596,
    688596, 688804, 688804, 688806, 688806, 688814, 688828, 689432,
    689432, 689434, 689434, 689522), PID = c("ANON1", "ANON2",
    "ANON3", "ANON4", "ANON5", "ANON6", "ANON7", "ANON8", "ANON9",
    "ANON10", "ANON11", "ANON12", "ANON13", "ANON14", "ANON15",
    "ANON16", "ANON17", "ANON18", "ANON19", "ANON20", "ANON21",
    "ANON22", "ANON23", "ANON24", "ANON25", "ANON26", "ANON27",
    "ANON28", "ANON29", "ANON30", "ANON31", "ANON32", "ANON33",
    "ANON34", "ANON35", "ANON36", "ANON37", "ANON38", "ANON39",
    "ANON40", "ANON41", "ANON42", "ANON43", "ANON44", "ANON45",
    "ANON46", "ANON47", "ANON48", "ANON49", "ANON50", "ANON51",
    "ANON52", "ANON53", "ANON54", "ANON55", "ANON56", "ANON57",
    "ANON58", "ANON59", "ANON60", "ANON61", "ANON62", "ANON63",
    "ANON64", "ANON65", "ANON66", "ANON67", "ANON68", "ANON69",
    "ANON70", "ANON71", "ANON72", "ANON73", "ANON74", "ANON75",
    "ANON76", "ANON77", "ANON78", "ANON79", "ANON80", "ANON81",
    "ANON82", "ANON83", "ANON84", "ANON85", "ANON86", "ANON87",
    "ANON88", "ANON89", "ANON90", "ANON91", "ANON92", "ANON93",
    "ANON94", "ANON95", "ANON96", "ANON97", "ANON98", "ANON99",
    "ANON100", "ANON101", "ANON102", "ANON103", "ANON104", "ANON105",
    "ANON106", "ANON107", "ANON108", "ANON109", "ANON110", "ANON111",
    "ANON112", "ANON113", "ANON114", "ANON115", "ANON116", "ANON117",
    "ANON118", "ANON119", "ANON120", "ANON121", "ANON122", "ANON123",
    "ANON124", "ANON125", "ANON126", "ANON127", "ANON128", "ANON129",
    "ANON130", "ANON131"), Day = c("Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Wednesday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Thursday", "Friday", "Friday", "Friday",
    "Friday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Tuesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Thursday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Wednesday", "Friday",
    "Tuesday", "Thursday", "Thursday", "Thursday", "Thursday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Wednesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Friday", "Friday", "Friday", "Wednesday",
    "Wednesday", "Wednesday", "Wednesday", "Thursday", "Thursday",
    "Friday", "Friday", "Wednesday", "Wednesday", "Wednesday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Wednesday",
    "Wednesday", "Thursday", "Thursday", "Friday", "Friday",
    "Thursday", "Thursday", "Wednesday", "Wednesday", "Wednesday",
    "Wednesday", "Wednesday", "Thursday", "Thursday", "Thursday",
    "Thursday", "Thursday", "Tuesday", "Tuesday", "Tuesday",
    "Tuesday", "Tuesday", "Tuesday", "Tuesday", "Wednesday",
    "Thursday", "Thursday", "Wednesday", "Wednesday", "Wednesday",
    "Thursday", "Thursday", "Friday", "Friday", "Friday", "Friday",
    "Friday", "Friday", "Friday", "Friday", "Thursday", "Thursday",
    "Thursday", "Friday", "Friday", "Friday", "Friday", "Saturday",
    "Wednesday", "Thursday", "Thursday", "Thursday", "Thursday",
    "Tuesday"), Operation = c("Text 1", "Text 2", "Text 3", "Text 4",
    "Text 5", "Text 6", "Text 7", "Text 8", "Text 9", "Text 10",
    "Text 11", "Text 12", "Text 13", "Text 14", "Text 15", "Text 16",
    "Text 17", "Text 18", "Text 19", "Text 20", "Text 21", "Text 22",
    "Text 23", "Text 24", "Text 25", "Text 26", "Text 27", "Text 28",
    "Text 29", "Text 30", "Text 31", "Text 32", "Text 33", "Text 34",
    "Text 35", "Text 36", "Text 37", "Text 38", "Text 39", "Text 40",
    "Text 41", "Text 42", "Text 43", "Text 44", "Text 45", "Text 46",
    "Text 47", "Text 48", "Text 49", "Text 50", "Text 51", "Text 52",
    "Text 53", "Text 54", "Text 55", "Text 56", "Text 57", "Text 58",
    "Text 59", "Text 60", "Text 61", "Text 62", "Text 63", "Text 64",
    "Text 65", "Text 66", "Text 67", "Text 68", "Text 69", "Text 70",
    "Text 71", "Text 72", "Text 73", "Text 74", "Text 75", "Text 76",
    "Text 77", "Text 78", "Text 79", "Text 80", "Text 81", "Text 82",
    "Text 83", "Text 84", "Text 85", "Text 86", "Text 87", "Text 88",
    "Text 89", "Text 90", "Text 91", "Text 92", "Text 93", "Text 94",
    "Text 95", "Text 96", "Text 97", "Text 98", "Text 99", "Text 100",
    "Text 101", "Text 102", "Text 103", "Text 104", "Text 105",
    "Text 106", "Text 107", "Text 108", "Text 109", "Text 110",
    "Text 111", "Text 112", "Text 113", "Text 114", "Text 115",
    "Text 116", "Text 117", "Text 118", "Text 119", "Text 120",
    "Text 121", "Text 122", "Text 123", "Text 124", "Text 125",
    "Text 126", "Text 127", "Text 128", "Text 129", "Text 130",
    "Text 131"), Specialty = c("Text 1", "Text 2", "Text 3",
    "Text 4", "Text 5", "Text 6", "Text 7", "Text 8", "Text 9",
    "Text 10", "Text 11", "Text 12", "Text 13", "Text 14", "Text 15",
    "Text 16", "Text 17", "Text 18", "Text 19", "Text 20", "Text 21",
    "Text 22", "Text 23", "Text 24", "Text 25", "Text 26", "Text 27",
    "Text 28", "Text 29", "Text 30", "Text 31", "Text 32", "Text 33",
    "Text 34", "Text 35", "Text 36", "Text 37", "Text 38", "Text 39",
    "Text 40", "Text 41", "Text 42", "Text 43", "Text 44", "Text 45",
    "Text 46", "Text 47", "Text 48", "Text 49", "Text 50", "Text 51",
    "Text 52", "Text 53", "Text 54", "Text 55", "Text 56", "Text 57",
    "Text 58", "Text 59", "Text 60", "Text 61", "Text 62", "Text 63",
    "Text 64", "Text 65", "Text 66", "Text 67", "Text 68", "Text 69",
    "Text 70", "Text 71", "Text 72", "Text 73", "Text 74", "Text 75",
    "Text 76", "Text 77", "Text 78", "Text 79", "Text 80", "Text 81",
    "Text 82", "Text 83", "Text 84", "Text 85", "Text 86", "Text 87",
    "Text 88", "Text 89", "Text 90", "Text 91", "Text 92", "Text 93",
    "Text 94", "Text 95", "Text 96", "Text 97", "Text 98", "Text 99",
    "Text 100", "Text 101", "Text 102", "Text 103", "Text 104",
    "Text 105", "Text 106", "Text 107", "Text 108", "Text 109",
    "Text 110", "Text 111", "Text 112", "Text 113", "Text 114",
    "Text 115", "Text 116", "Text 117", "Text 118", "Text 119",
    "Text 120", "Text 121", "Text 122", "Text 123", "Text 124",
    "Text 125", "Text 126", "Text 127", "Text 128", "Text 129",
    "Text 130", "Text 131"), Booked = c(150, 150, 90, 50, 90,
    90, 75, 180, 120, 75, 120, 90, 60, 120, 90, 90, 45, 45, 45,
    60, 70, 30, 60, 90, 240, 90, 180, 180, 60, 60, 60, 540, 810,
    480, 810, 60, 120, 60, 60, 82, 90, 90, 119, 90, 75, 70, 240,
    60, 150, 60, 90, 90, 105, 60, 110, 90, 75, 240, 120, 90,
    90, 120, 90, 180, 360, 60, 420, 60, 240, 90, 90, 60, 90,
    60, 240, 280, 150, 181, 280, 240, 240, 360, 240, 240, 120,
    120, 75, 90, 90, 120, 60, 60, 75, 75, 90, 90, 60, 60, 60,
    90, 500, 510, 152, 363, 87, 227, 150, 528, 123, 300, 150,
    100, 60, 60, 50, 40, 50, 90, 90, 60, 60, 120, 240, 120, 427,
    540, 240, 90, 240, 60, 240), Available = c(540, 540, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540,
    540, 540, 540, 540, 540, 810, 540, 810, 540, 540, 540, 540,
    240, 240, 240, 240, 240, 240, 240, 240, 540, 540, 540, 540,
    540, 240, 240, 240, 240, 240, 240, 240, 240, 540, 540, 540,
    540, 540, 540, 540, 540, 240, 240, 240, 240, 240, 240, 540,
    540, 540, 540, 540, 540, 540, 540, 540, 540, 240, 240, 240,
    240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
    240, 540, 540, 540, 540, 540, 540, 540, 540, 540, 540, 240,
    240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
    240, 240, 540, 240, 240, 240, 240, 240), Theatre = c("03",
    "03", "03", "03", "03", "03", "03", "03", "03", "03", "03",
    "03", "03", "03", "04", "04", "04", "04", "04", "04", "04",
    "04", "04", "04", "04", "04", "04", "04", "04", "04", "04",
    "05", "05", "05", "06", "06", "06", "06", "06", "07", "07",
    "07", "07", "07", "07", "07", "07", "08", "08", "08", "08",
    "08", "08", "08", "08", "08", "08", "08", "08", "08", "09",
    "09", "09", "09", "09", "09", "09", "09", "10", "10", "10",
    "11", "11", "11", "12", "12", "12", "12", "12", "12", "12",
    "12", "05", "05", "07", "07", "07", "07", "07", "08", "08",
    "08", "08", "08", "09", "09", "09", "09", "09", "09", "14",
    "14", "14", "14", "15", "15", "15", "15", "15", "15", "04",
    "04", "04", "04", "04", "04", "04", "11", "11", "11", "06",
    "06", "06", "06", "15", "06", "10", "10", "10", "10", "03"
    ), Priority = c(3, 3, 2, 1, 1, 1, 2, 1, 4, 2, 4, 4, 2, 3,
    2, 4, 2, 1, 2, 3, 2, 2, 3, 1, 4, 1, 1, 1, 2, 3, 2, 3, 1,
    4, 4, 3, 4, 2, 2, 2, 2, 1, 1, 1, 2, 2, 1, 4, 1, 4, 2, 4,
    2, 1, 1, 4, 3, 3, 2, 2, 4, 4, 2, 1, 2, 4, 3, 4, 4, 1, 4,
    4, 3, 1, 3, 1, 4, 4, 2, 4, 3, 1, 1, 4, 1, 1, 2, 2, 3, 1,
    3, 4, 4, 4, 4, 1, 4, 4, 2, 4, 2, 3, 3, 1, 3, 2, 1, 3, 4,
    1, 4, 4, 1, 1, 3, 4, 2, 1, 4, 2, 3, 2, 3, 4, 2, 4, 1, 1,
    1, 1, 3), Session = c("All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "AM",
    "AM", "PM", "PM", "AM", "AM", "AM", "PM", "All Day", "All Day",
    "All Day", "All Day", "All Day", "AM", "AM", "AM", "PM",
    "PM", "AM", "PM", "PM", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "AM",
    "PM", "PM", "PM", "PM", "PM", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "AM", "AM", "PM", "PM", "PM", "AM", "AM", "PM",
    "PM", "PM", "AM", "AM", "AM", "PM", "PM", "PM", "All Day",
    "All Day", "All Day", "All Day", "All Day", "All Day", "All Day",
    "All Day", "All Day", "All Day", "AM", "AM", "PM", "PM",
    "PM", "PM", "PM", "PM", "PM", "PM", "AM", "AM", "PM", "PM",
    "AM", "All Day", "AM", "AM", "PM", "PM", "AM"), WardTo = c(40,
    15, 5, 33, 11, 18, 40, 19, 12, 34, 41, 24, 9, 23, 36, 26,
    25, 31, 46, 30, 12, 4, 27, 32, 48, 46, 3, 23, 44, 1, 35,
    45, 9, 34, 21, 28, 26, 23, 20, 37, 39, 2, 42, 36, 35, 6,
    36, 6, 11, 39, 13, 12, 28, 50, 47, 16, 26, 2, 33, 38, 50,
    47, 49, 10, 7, 49, 36, 44, 42, 2, 38, 19, 43, 21, 12, 10,
    48, 10, 14, 42, 2, 39, 11, 41, 18, 41, 47, 15, 39, 8, 11,
    17, 11, 12, 12, 20, 50, 12, 2, 46, 13, 6, 4, 22, 8, 3, 11,
    27, 12, 12, 14, 27, 23, 48, 25, 49, 49, 30, 1, 28, 35, 9,
    37, 21, 27, 25, 31, 18, 13, 3, 7), Order = c(1, 2, 3, 4,
    5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 7, 8, 1,
    2, 3, 4, 1, 2, 3, 4, 5, 1, 1, 1, 1, 1, 2, 3, 4, 1, 2, 1,
    2, 1, 2, 3, 1, 1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 1, 1, 2, 1,
    2, 3, 4, 1, 2, 1, 2, 1, 1, 2, 1, 2, 3, 1, 2, 1, 2, 1, 2,
    1, 2, 1, 2, 1, 2, 1, 2, 3, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2,
    3, 1, 1, 1, 2, 1, 2, 3, 1, 2, 1, 1, 2, 1, 2, 3, 4, 5, 1,
    2, 3, 1, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1), Surgeon = c(2, 2,
    5, 4, 9, 4, 8, 4, 5, 7, 9, 7, 8, 8, 10, 6, 6, 1, 2, 1, 4,
    5, 7, 4, 9, 4, 6, 10, 1, 3, 10, 4, 8, 9, 4, 3, 2, 7, 6, 5,
    1, 5, 10, 8, 5, 8, 10, 4, 10, 4, 3, 4, 7, 8, 5, 9, 8, 1,
    5, 10, 3, 1, 3, 6, 10, 7, 8, 3, 5, 1, 2, 6, 5, 9, 10, 4,
    9, 2, 4, 10, 5, 7, 2, 6, 8, 3, 9, 2, 4, 1, 9, 9, 2, 3, 9,
    8, 9, 6, 10, 5, 7, 9, 2, 5, 7, 2, 10, 2, 2, 1, 1, 2, 6, 5,
    3, 10, 2, 4, 3, 3, 3, 9, 9, 7, 1, 6, 3, 5, 5, 10, 2)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -131L))


问:
Implement pagination in Flutter with a bloc pattern
Using the NotificationListener, I am trying to integrate pagination with the ListView.Builder, but I don't get the expected result. While the list is working, it scrolls very slowly.

The code I wrote is below

```<code>NotificationListener<ScrollNotification>(
  onNotification: (scrollNotification) {
    if (_controller.position.maxScrollExtent ==
        _controller.offset) {
      if (state is LoghistorySuccess) {
        if (logsData.length == _index) {
          if (pagecount > page) {
            setState(() {
              page = page + 1;
              print(page);
              BlocProvider.of<LogHistoryBloc>(
                      context)
                  .add(LogHistoryFetchEvent(
                      page: page));
            });
          }
        }
      }
    }

    if (scrollNotification
        is ScrollStartNotification) {
      _onStartScroll(scrollNotification.metrics);
    } else if (scrollNotification
        is ScrollUpdateNotification) {
      _onUpdateScroll(scrollNotification.metrics);
    } else if (scrollNotification
        is ScrollEndNotification) {
      _onEndScroll(scrollNotification.metrics);
    }
    return true;
  },
  child: logsData.isNotEmpty
      ? ListView.builder(
          controller: _controller,
          shrinkWrap: true,
          scrollDirection: Axis.vertical,
          itemCount: logsData.length,
          //state.logHistoryModel.results?.logs?.length ?? 0,
          itemBuilder: (context, index) {
            return Padding(
              padding:
                  const EdgeInsets.only(top: 12.0),
              child: DottedBorder(
                  borderType: BorderType.RRect,
                  strokeWidth: 1,
                  dashPattern: [2.5, 2.5],
                  color:
                      HexColor(Constants.primary),
                  radius: Radius.circular(10),
                  child: Padding(
                    padding: const EdgeInsets.only(
                        top: 15.0,
                        left: 15,
                        right: 15,
                        bottom: 8.0),
                    child: Column(
                      crossAxisAlignment:
                          CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment:
                              MainAxisAlignment
                                  .spaceBetween,
                          children: [
                            Container(
                              width: MediaQuery.of(
                                          context)
                                      .size
                                      .width /
                                  2,
                              child: Text(
                                  "${logsData[index].date}",
                                  style: TextStyle(
                                    overflow:
                                        TextOverflow
                                            .ellipsis,
                                    fontWeight:
                                        FontWeight
                                            .w500,
                                    fontSize: 16,
                                    color: HexColor(
                                        Constants
                                            .primary),
                                  )),
                            ),
                            // Text(
                            //   "${state.logHistoryEntity.logs?[index]["entry_date"]}",
                            //   style: TextStyle(
                            //       color:
                            //           Color(0xff555B5F)),
                            // ),
                          ],
                        ),
                        Container(
                          margin: EdgeInsets.only(
                            top: 15,
                          ),
                          child: ListView.builder(
                            shrinkWrap: true,
                            physics:
                                NeverScrollableScrollPhysics(),
                            itemCount:
                                logsData[index]
                                        .log
                                        ?.length ??
                                    0,
                            //state.logHistoryModel.results?.logs?[index].log?.length ?? 0,
                            itemBuilder:
                                (context, _index) {
                              var _data =
                                  logsData[index]
                                      .log?[_index];
                              return Padding(
                                padding:
                                    const EdgeInsets
                                            .only(
                                        bottom:
                                            8.0),
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment
                                          .spaceBetween,
                                  children: [
                                    InkWell(
                                      onTap: () {
                                        summaryPopUp(
                                            context,
                                            _data!);
                                      },
                                      child: Text(
                                        "• ${_data?.startTime} to ${_data?.endTime}",
                                        style: TextStyle(
                                            color: Color(
                                                0xff555B5F)),
                                      ),
                                    ),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment
                                              .spaceBetween,
                                      children: [
                                        Text(
                                          "${_data?.logtype}",
                                          style: TextStyle(
                                              color:
                                                  Color(0xffED5B2E)),
                                        ),
                                        SizedBox(
                                          width: 20,
                                        ),
                                        _data?.createdDate ==
                                                formatted
                                            ? Row(
                                                children: [
                                                  InkWell(
                                                    onTap: () {
                                                      Navigator.pushReplacement(
                                                          context,
                                                          MaterialPageRoute(
                                                            builder: (context) => EditLogsScreen(log: _data!),
                                                          ));
                                                    },
                                                    child: ImageIcon(
                                                      AssetImage("assets/icons/pencil.png"),
                                                      color: Color(0xff18A558),
                                                      size: 20,
                                                    ),
                                                  ),
                                                  SizedBox(
                                                    width: 8,
                                                  ),
                                                  InkWell(
                                                    onTap: () {
                                                      showDialog(
                                                        context: context,
                                                        builder: (context) {
                                                          return DeletLogConfPopUp(
                                                            logId: _data?.id,
                                                            log: logsData[_index].log,
                                                            index: _index,
                                                          );
                                                        },
                                                      );
                                                    },
                                                    child: ImageIcon(
                                                      AssetImage("assets/icons/delete_icon.png"),
                                                      color: Color(0xffE72323),
                                                      size: 18,
                                                    ),
                                                  ),
                                                ],
                                              )
                                            : Container()
                                      ],
                                    )
                                  ],
                                ),
                              );
                            },
                          ),
                        )
                      ],
                    ),
                  )),
            );
          },
        )
      : Container(),
  // Center(
  //         child: Column(
  //           children: [
  //             Image(
  //                 image: AssetImage(
  //                     "assets/images/no_task.png")),
  //             Text("You don't have any logs yet")
  //           ],
  //         ),
  //       ),
)
</code>```

with this code pagination works fine but not scrolling fast.

Body:
Using the NotificationListener, I am trying to integrate pagination with the ListView.Builder, but I don't get the expected result. While the list is working, it scrolls very slowly.

The code I wrote is below

NotificationListener<ScrollNotification>(
  onNotification: (scrollNotification) {
    if (_controller.position.maxScrollExtent ==
        _controller.offset) {
      if (state is LoghistorySuccess) {
        if (logsData.length == _index) {
          if (pagecount > page) {
            setState(() {
              page = page + 1;
              print(page);
              BlocProvider.of<LogHistoryBloc>(
                      context)
                  .add(LogHistoryFetchEvent(
                      page: page));
            });
          }
        }
      }
    }

    if (scrollNotification
        is ScrollStartNotification) {
      _onStartScroll(scrollNotification.metrics);
    } else if (scrollNotification
        is ScrollUpdateNotification) {
      _onUpdateScroll(scrollNotification.metrics);
    } else if (scrollNotification
        is ScrollEndNotification) {
      _onEndScroll(scrollNotification.metrics);
    }
    return true;
  },
  child: logsData.isNotEmpty
      ? ListView.builder(
          controller: _controller,
          shrinkWrap: true,
          scrollDirection: Axis.vertical,
          itemCount: logsData.length,
          //state.logHistoryModel.results?.logs?.length ?? 0,
          itemBuilder: (context, index) {
            return Padding(
              padding:
                  const EdgeInsets.only(top: 12.0),
              child: DottedBorder(
                  borderType: BorderType.RRect,
                  strokeWidth: 1,
                  dashPattern: [2.5, 2.5],
                  color:
                      HexColor(Constants.primary),
                  radius: Radius.circular(10),
                  child: Padding(
                    padding: const EdgeInsets.only(
                        top: 15.0,
                        left: 15,
                        right: 15,
                        bottom: 8.0),
                    child: Column(
                      crossAxisAlignment:
                          CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment:
                              MainAxisAlignment
                                  .spaceBetween,
                          children: [
                            Container(
                              width: MediaQuery.of(
                                          context)
                                      .size
                                      .width /
                                  2,
                              child: Text(
                                  "${logsData[index].date}",
                                  style: TextStyle(
                                    overflow:
                                        TextOverflow
                                            .ellipsis,
                                    fontWeight:
                                        FontWeight
                                            .w500,
                                    fontSize: 16,
                                    color: HexColor(
                                        Constants
                                            .primary),
                                  )),
                            ),
                            // Text(
                            //   "${state.logHistoryEntity.logs?[index]["entry_date"]}",
                            //   style: TextStyle(
                            //       color:
                            //           Color(0xff555B5F)),
                            // ),
                          ],
                        ),
                        Container(
                          margin: EdgeInsets.only(
                            top: 15,
                          ),
                          child: ListView.builder(
                            shrinkWrap: true,
                            physics:
                                NeverScrollableScrollPhysics(),
                            itemCount:
                                logsData[index]
                                        .log
                                        ?.length ??
                                    0,
                            //state.logHistoryModel.results?.logs?[index].log?.length ?? 0,
                            itemBuilder:
                                (context, _index) {
                              var _data =
                                  logsData[index]
                                      .log?[_index];
                              return Padding(
                                padding:
                                    const EdgeInsets
                                            .only(
                                        bottom:
                                            8.0),
                                child: Row(
                                  mainAxisAlignment:
                                      MainAxisAlignment
                                          .spaceBetween,
                                  children: [
                                    InkWell(
                                      onTap: () {
                                        summaryPopUp(
                                            context,
                                            _data!);
                                      },
                                      child: Text(
                                        "• ${_data?.startTime} to ${_data?.endTime}",
                                        style: TextStyle(
                                            color: Color(
                                                0xff555B5F)),
                                      ),
                                    ),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment
                                              .spaceBetween,
                                      children: [
                                        Text(
                                          "${_data?.logtype}",
                                          style: TextStyle(
                                              color:
                                                  Color(0xffED5B2E)),
                                        ),
                                        SizedBox(
                                          width: 20,
                                        ),
                                        _data?.createdDate ==
                                                formatted
                                            ? Row(
                                                children: [
                                                  InkWell(
                                                    onTap: () {
                                                      Navigator.pushReplacement(
                                                          context,
                                                          MaterialPageRoute(
                                                            builder: (context) => EditLogsScreen(log: _data!),
                                                          ));
                                                    },
                                                    child: ImageIcon(
                                                      AssetImage("assets/icons/pencil.png"),
                                                      color: Color(0xff18A558),
                                                      size: 20,
                                                    ),
                                                  ),
                                                  SizedBox(
                                                    width: 8,
                                                  ),
                                                  InkWell(
                                                    onTap: () {
                                                      showDialog(
                                                        context: context,
                                                        builder: (context) {
                                                          return DeletLogConfPopUp(
                                                            logId: _data?.id,
                                                            log: logsData[_index].log,
                                                            index: _index,
                                                          );
                                                        },
                                                      );
                                                    },
                                                    child: ImageIcon(
                                                      AssetImage("assets/icons/delete_icon.png"),
                                                      color: Color(0xffE72323),
                                                      size: 18,
                                                    ),
                                                  ),
                                                ],
                                              )
                                            : Container()
                                      ],
                                    )
                                  ],
                                ),
                              );
                            },
                          ),
                        )
                      ],
                    ),
                  )),
            );
          },
        )
      : Container(),
  // Center(
  //         child: Column(
  //           children: [
  //             Image(
  //                 image: AssetImage(
  //                     "assets/images/no_task.png")),
  //             Text("You don't have any logs yet")
  //           ],
  //         ),
  //       ),
)

with this code pagination works fine but not scrolling fast.


问:
Openweather API linking the searchbar to the actual city chosen from the hard coding part
I am currently working on a weather app using Openweather API, and I'm having a little strugle on creating the function that in the moment that a city is written in the search bar and the button search is pressed, I want the h1 with the class "chosen-location" textcontent to change into the input from the search bar, this thing should happen by changing the value of the variable city into the content from the searchbar. That's how I would do it if I would have some more expierence, but I don't know how to really write all this stuff.

const apikey = `45d2b1974108dfa1128c4ce9991a1f56`;
let city = "Constanta";
let search = document.querySelector('.searchbar');
let button = document.querySelector('.btn');

window.addEventListener('load', ()=>{
    let long;
    let lat;
    let temperatureDescription = document.querySelector('.temperature-description');
    let temperatureDegree = document.querySelector('.degree');
    let locationTimezone = document.querySelector('.location-timezone');
    let icon = document.querySelector('.icon');

    if(navigator.geolocation){
        navigator.geolocation.getCurrentPosition(position => {
            long = position.coords.longitude;
            lat = position.coords.latitude;
            // what i've done here takes your coordinates and puts them to the variables mentioned

            const api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&APPID=${apikey}&units=metric`;
            fetch(api)
            .then(respones => {
                return respones.json();
            })
            .then(data =>{
                console.log(data);

                const {temp} = data.main;
                const {main} = data.weather[0];
                const {country} = data.sys;

                // set DOM elements from the API

                temperatureDegree.textContent = temp;
                temperatureDescription.textContent = main;
                locationTimezone.textContent = country;

                if(temperatureDescription.textContent === 'Mist'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/50d@2x.png';
                }if(temperatureDescription.textContent === 'Clear Sky'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/01d@2x.png';
                }if(temperatureDescription.textContent === 'Clouds'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/03d@2x.png';
                }if(temperatureDescription.textContent === 'Rain'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/10d@2x.png';
                }if(temperatureDescription.textContent === 'Thunderstorm'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/11d@2x.png';
                }if(temperatureDescription.textContent === 'Snow'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/13d@2x.png';
                }

               console.log(temperatureDescription.textContent);

            });});

    }

});```
</div>
</div>
</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title> Weather app </title>
</head>
<body>

    <div class="location">
        <h1 class="location-timezone">Timezone</h1>
        <h1 class="chosen-location">Constanta</h1>
        <img class= "icon" src="http://openweathermap.org/img/wn/01d@2x.png" alt="weather">

    </div>
    <div class="search"><input type="text" placeholder="Ex:Chicago" class="searchbar"></div> <button class="btn">Search</button>
    <div class="temperature">
        <div class="degree-section">
        <h2 class="degree">34</h2>
        <span> Celsius</span>
        </div>

        <div class="temperature-description">It's frkin cold</div>
    </div>

    <script type ="module" src="script.js"></script>

</body>
</html></code>```

Body:
I am currently working on a weather app using Openweather API, and I'm having a little strugle on creating the function that in the moment that a city is written in the search bar and the button search is pressed, I want the h1 with the class "chosen-location" textcontent to change into the input from the search bar, this thing should happen by changing the value of the variable city into the content from the searchbar. That's how I would do it if I would have some more expierence, but I don't know how to really write all this stuff.

const apikey = `45d2b1974108dfa1128c4ce9991a1f56`;
let city = "Constanta";
let search = document.querySelector('.searchbar');
let button = document.querySelector('.btn');

window.addEventListener('load', ()=>{
    let long;
    let lat;
    let temperatureDescription = document.querySelector('.temperature-description');
    let temperatureDegree = document.querySelector('.degree');
    let locationTimezone = document.querySelector('.location-timezone');
    let icon = document.querySelector('.icon');

    if(navigator.geolocation){
        navigator.geolocation.getCurrentPosition(position => {
            long = position.coords.longitude;
            lat = position.coords.latitude;
            // what i've done here takes your coordinates and puts them to the variables mentioned

            const api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&APPID=${apikey}&units=metric`;
            fetch(api)
            .then(respones => {
                return respones.json();
            })
            .then(data =>{
                console.log(data);

                const {temp} = data.main;
                const {main} = data.weather[0];
                const {country} = data.sys;

                // set DOM elements from the API

                temperatureDegree.textContent = temp;
                temperatureDescription.textContent = main;
                locationTimezone.textContent = country;

                if(temperatureDescription.textContent === 'Mist'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/50d@2x.png';
                }if(temperatureDescription.textContent === 'Clear Sky'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/01d@2x.png';
                }if(temperatureDescription.textContent === 'Clouds'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/03d@2x.png';
                }if(temperatureDescription.textContent === 'Rain'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/10d@2x.png';
                }if(temperatureDescription.textContent === 'Thunderstorm'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/11d@2x.png';
                }if(temperatureDescription.textContent === 'Snow'){
                    document.querySelector('.icon').src='http://openweathermap.org/img/wn/13d@2x.png';
                }

               console.log(temperatureDescription.textContent);

            });});

    }

});

<!DOCTYPE html>

    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">
    <title> Weather app </title>

Timezone

Constanta

<input type="text" placeholder="Ex:Chicago" class="searchbar">
 <button class="btn">Search</button>

34

         Celsius

It's frkin cold


问:
execute test cases before build
I have a python project created using pycharm. Am able to run the test cases manually using pytest. I need to run the test cases before build automatically ...

Below is my project structure

```<code>Hadoop
  src
    apps
      app1.py
      __init__.py
    __init__.py
  test
    tests
      test_checks.py
    __init__.py
  __init__.py
setup.py
</code>```

Am able to right click on test folder and run the select "run pytest in test" option and the test cases starts execution.

Below is my setup.py

```<code>setup(
name="databricks",
# packages=find_packages(),
packages=find_namespace_packages('src'),
# packages=find_packages('src'),
package_dir={'': 'src'},
description="Test package to execute on databricks using DBX",
# setup_requires=["wheel"],
setup_requires=['pytest-runner', "wheel"],
version="0.0.0",
author="Sasidhar Reddy",
author_email="sasidhar446@gmail.com",
test_suite="test",
tests_require=['pytest'],
entry_points={
    "console_scripts": [
        "test_cli = apps:app1:main",
    ]
},
)
</code>```

I want to run the testcases just before the project build is started.

Title: execute test cases before build

Body:
I have a python project created using pycharm. Am able to run the test cases manually using pytest. I need to run the test cases before build automatically ...

Below is my project structure

Hadoop
  src
    apps
      app1.py
      __init__.py
    __init__.py
  test
    tests
      test_checks.py
    __init__.py
  __init__.py
setup.py

Am able to right click on test folder and run the select "run pytest in test" option and the test cases starts execution.

Below is my setup.py

setup(
name="databricks",
# packages=find_packages(),
packages=find_namespace_packages('src'),
# packages=find_packages('src'),
package_dir={'': 'src'},
description="Test package to execute on databricks using DBX",
# setup_requires=["wheel"],
setup_requires=['pytest-runner', "wheel"],
version="0.0.0",
author="Sasidhar Reddy",
author_email="sasidhar446@gmail.com",
test_suite="test",
tests_require=['pytest'],
entry_points={
    "console_scripts": [
        "test_cli = apps:app1:main",
    ]
},
)

I want to run the testcases just before the project build is started.


问:
How to remove read-only in a new copy using Open XML SDK
I have come across two spreadsheets giving me errors when using Open XML SDK to convert.

The cases are:

Read-only password protection (I don't have password)

Filesharing enabled (another user on the network has the spreadsheet open and spreadsheet is read-only until user closes spreadsheet)

If I use Excel Interop, it is possible to give parameters that will open a copy of the spreadsheet and enable write permissions and hence any programmatic conversion process can continue. This code enables the behaviour by utilising IgnoreReadOnlyRecommended

```<code>// Convert legacy Excel files to .xlsx Transitional using Microsoft Office Interop Excel
public bool Convert_Legacy_ExcelInterop(string input_filepath, string output_filepath)
{
    bool convert_success = false;

    // Open Excel
    Excel.Application app = new Excel.Application(); // Create Excel object instance
    app.DisplayAlerts = false; // Don't display any Excel prompts
    Excel.Workbook wb = app.Workbooks.Open(input_filepath, ReadOnly: false, Password: "'", WriteResPassword: "'", IgnoreReadOnlyRecommended: true, Notify: false); // Create workbook instance

    // Save workbook as .xlsx Transitional and close Excel
    wb.SaveAs(output_filepath, 51);
    wb.Close();
    app.Quit();

    return convert_success = true;
}
</code>```

How can I imitate the same behaviour using Open XML SDK?

Here's my code:

```<code>// Convert to .xlsx Transitional
public bool Convert_to_OOXML_Transitional(string input_filepath, string output_filepath)
{
    bool convert_success = false;

    // If write-protected or reserved by another user
    using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(input_filepath, false))
    {
        if (spreadsheet.WorkbookPart.Workbook.WorkbookProtection != null || spreadsheet.WorkbookPart.Workbook.FileSharing != null)
        {
            // Use Excel Interop to convert the spreadsheet
            Convert_Legacy_ExcelInterop(input_filepath, output_filepath);
            return convert_success = true;
            // REPLACE ABOVE CODE WITH SOMETHING NATIVE TO OPEN XML SDK

        }
    }

    // Convert spreadsheet
    byte[] byteArray = File.ReadAllBytes(input_filepath);
    using (MemoryStream stream = new MemoryStream())
    {
        stream.Write(byteArray, 0, (int)byteArray.Length);
        using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(stream, true))
        {
            spreadsheet.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
        }
        File.WriteAllBytes(output_filepath, stream.ToArray());
    }

    // Repair spreadsheet
    Repair rep = new Repair();
    rep.Repair_OOXML(output_filepath);

    // Return success
    convert_success = true;
    return convert_success;
}
</code>```

Body:
I have come across two spreadsheets giving me errors when using Open XML SDK to convert.

The cases are:

Read-only password protection (I don't have password)

Filesharing enabled (another user on the network has the spreadsheet open and spreadsheet is read-only until user closes spreadsheet)

If I use Excel Interop, it is possible to give parameters that will open a copy of the spreadsheet and enable write permissions and hence any programmatic conversion process can continue. This code enables the behaviour by utilising IgnoreReadOnlyRecommended

// Convert legacy Excel files to .xlsx Transitional using Microsoft Office Interop Excel
public bool Convert_Legacy_ExcelInterop(string input_filepath, string output_filepath)
{
    bool convert_success = false;

    // Open Excel
    Excel.Application app = new Excel.Application(); // Create Excel object instance
    app.DisplayAlerts = false; // Don't display any Excel prompts
    Excel.Workbook wb = app.Workbooks.Open(input_filepath, ReadOnly: false, Password: "'", WriteResPassword: "'", IgnoreReadOnlyRecommended: true, Notify: false); // Create workbook instance

    // Save workbook as .xlsx Transitional and close Excel
    wb.SaveAs(output_filepath, 51);
    wb.Close();
    app.Quit();

    return convert_success = true;
}

How can I imitate the same behaviour using Open XML SDK?

Here's my code:

// Convert to .xlsx Transitional
public bool Convert_to_OOXML_Transitional(string input_filepath, string output_filepath)
{
    bool convert_success = false;

    // If write-protected or reserved by another user
    using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(input_filepath, false))
    {
        if (spreadsheet.WorkbookPart.Workbook.WorkbookProtection != null || spreadsheet.WorkbookPart.Workbook.FileSharing != null)
        {
            // Use Excel Interop to convert the spreadsheet
            Convert_Legacy_ExcelInterop(input_filepath, output_filepath);
            return convert_success = true;
            // REPLACE ABOVE CODE WITH SOMETHING NATIVE TO OPEN XML SDK

        }
    }

    // Convert spreadsheet
    byte[] byteArray = File.ReadAllBytes(input_filepath);
    using (MemoryStream stream = new MemoryStream())
    {
        stream.Write(byteArray, 0, (int)byteArray.Length);
        using (SpreadsheetDocument spreadsheet = SpreadsheetDocument.Open(stream, true))
        {
            spreadsheet.ChangeDocumentType(SpreadsheetDocumentType.Workbook);
        }
        File.WriteAllBytes(output_filepath, stream.ToArray());
    }

    // Repair spreadsheet
    Repair rep = new Repair();
    rep.Repair_OOXML(output_filepath);

    // Return success
    convert_success = true;
    return convert_success;
}