diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 000000000..4e4d057df --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,19 @@ +--- +name: Question +about: Ask a question about Thoth +title: '' +labels: question +assignees: '' + +--- + +**My question relates to** +Please mark with an "x": +- [ ] Thoth APP (graphical interface) +- [ ] Thoth GraphQL API +- [ ] Thoth Export API +- [ ] Something else + + +**My question is** +Write your question here diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fac43a40..2bcbf8e59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [[0.7.2]](https://github.com/thoth-pub/thoth/releases/tag/v0.7.2) - 2022-02-08 +### Changed + - [#339](https://github.com/thoth-pub/thoth/pull/339) - Update publication types to include AZW3, DOCX and FictionBook + - [#331](https://github.com/thoth-pub/thoth/pull/331) - Update series model to include description and CFP URL + - Allow triggering docker action manually + +### Added + - Add code of conduct and support document to repository + ## [[0.7.1]](https://github.com/thoth-pub/thoth/releases/tag/v0.7.1) - 2022-01-24 ### Changed - Removed redundant `to_string` calls to comply with [`rustc 1.58.0`](https://github.com/rust-lang/rust/releases/tag/1.58.0) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..7bfa1d067 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,776 @@ +**License:** [Creative Commons Attribution 4.0 International License +(CC-BY 4.0)](https://creativecommons.org/licenses/by/4.0/) + +# COPIM Code of Conduct + +Thoth is a development of the [COPIM project](https://www.copim.ac.uk/) +and, as such, its code of conduct applies to this repository. + +Why we Have a Code of Conduct +----------------------------- + +COPIM is a community-led and community-focused project. We value the +involvement of everyone in our community, and to enable this we are +committed to creating a friendly and respectful place for sharing, +exchange, and the development of programs and initiatives. All +participants in our events, projects, and communications are expected to +show respect and courtesy to others. + +COPIM is dedicated to providing a welcoming and supportive environment +for all people, regardless of background or identity. We believe our +community should be as diverse, inclusive, and accessible as possible. +We want our community to be a positive, safe and healthy environment for +anyone who joins (and wants to join) and we pledge to make participation +in our community a harassment-free experience for everyone. As such, we +do not tolerate behaviour that is [disrespectful or that excludes, +intimidates, or causes discomfort to others](#unacceptable-behaviour). +We do not tolerate discrimination or [harassment](#harassment) based on +characteristics that include, but are not limited to, gender identity, +orientation, and expression, sexual orientation, visible or invisible +disability, physical appearance, body size, citizenship, nationality, +ethnic or social origin, pregnancy, familial status, veteran status, +genetic information, religion or belief (or lack thereof), membership of +a national minority, property, age, education, socio-economic status, +technical choices, and experience level. We are committed to ensuring +that this remains so, including by embracing this Code of Conduct and +revisiting it for updates as needed. In short, to protect our projects +against those who damage or distort them, we pledge to act and interact +in ways that contribute to an open, welcoming, diverse, inclusive +community focused on the well-being of its members. + +This Code of Conduct defines a minimum set of guidelines of expected and +unacceptable behaviour. + +Who Does this CoC Apply To? +--------------------------- + +To make clear what is expected, everyone participating in COPIM's +activities is required to abide by the Code of Conduct. It applies +equally to everyone who interacts and contributes to COPIM projects and +spaces without any exceptions (e.g. we will make no exceptions based on +standing, skills or accomplishments in COPIM projects). This includes +project partners and members, event organisers and participants, and +board members of COPIM. + +By participating in this community, participants accept to abide by +COPIM's Code of Conduct and accept the procedures by which any Code of +Conduct incidents are resolved. It applies to all COPIM Work Packages +(WPs), technical spaces, in-person and virtual events, including +workshops and conferences (workshop and conference hosts are expected to +assist with the enforcement of the Code of Conduct), as well as the +following instances: + +- private, public and semi-public interactions + +- disagreements and expressions of solidarity across community members + +- issues of technical development + +- aspects of content contribution + +- cases of representing affiliates/communities with external partners + +This Code of Conduct applies to all spaces managed by COPIM including, +but not limited to, COPIM email lists and online fora such as GitHub, +Nextcloud, Mattermost, PubPub, Cryptpad, Big Blue Button, Zoom, Jitsi, +MS Teams, Twitter, and any other fora created by the project team which +the community uses for communication and exchange. In addition, +violations of this code outside these spaces may affect a person\'s +ability to participate within them. This Code of Conduct also applies +when an individual is officially representing the COPIM community in +public spaces. Examples of representing our community include using an +official e-mail address, posting via an official social media account, +or acting as an appointed representative at an online or offline event. + +By participating, participants and COPIM members indicate their +acceptance of the procedures by which COPIM resolves any Code of Conduct +incidents, which may include storage and processing of their personal +information. Actions that contradict the Code of Conduct can result in +sanctions (see [**Enforcement Guidelines**](#enforcement-guidelines)). + +### Our Values + +Any form of behaviour to exclude, intimidate, or cause discomfort is a +violation of the Code of Conduct. In order to foster a positive and +professional learning environment we encourage examples of the following +kinds of behaviours  that contributes to a positive environment for our +community in all platforms and events: + +- Use welcoming and inclusive language; + +- Be careful in the words that you choose; + +- Be friendly and patient; + +- Be respectful of different viewpoints, opinions, and experiences; + +- Show courtesy and respect towards other community members; + +- Demonstrate empathy and kindness towards other people; + +- Give and gracefully accept constructive criticism and feedback; + +- Accept responsibility and apologise to those affected by our + mistakes, and learn from the experience; + +- Focus on what is best not just for us as individuals, but for the + overall community + +In all COPIM projects, spaces and events, behaviour will be founded in +respect, civility, collegiality, solidarity, and good citizenship. This +applies to all contributors and participants in their interaction with +all contributors and participants. + +Your work will be used by other people, and you in turn will depend on +the work of others. Any decision you take will affect users and +colleagues, and you should take those consequences into account when +making decisions. Remember that we\'re an international community, so +you might not be communicating in someone else\'s primary language. + +Not all of us will agree all the time, but disagreement is no excuse for +poor behaviour and poor manners. We might all experience some +frustration now and then, but we cannot allow that frustration to turn +into a personal attack. It's important to remember that a community +where people feel uncomfortable or threatened is not a productive one. + +### Mutual Respect + +Members of the COPIM community should be respectful when dealing with +other members as well as with people outside the COPIM community. In +communicating with people, whether in online or offline COPIM +environments, we will treat each other with mutual respect. + +**Mutual respect includes following these practices:** + +- **Practice empathy.** Listen and try to understand what COPIM + members of different backgrounds want to tell you. Be ready to + challenge and adapt your own understanding, expectations and + behaviour as a COPIM member. + +- **Assume good faith and engage in constructive edits.** Your + contributions should improve the quality of the project or work. + Provide and receive feedback kindly and in good faith. Criticism + should be delivered in a sensitive and constructive manner. All + COPIM members should assume unless evidence otherwise exists that + others are here to collaboratively improve the projects, but this + should not be used to justify statements with a harmful impact. + +- **Respect the way that contributors name and describe + themselves.** People may use specific terms to describe themselves. + As a sign of respect, use these terms when communicating with or + about these people, where linguistically or technically feasible. + Examples include: + +- Ethnic groups may use a specific name to describe themselves, rather + than the name historically used by others; + +- People may have names that use letters, sounds, or words from their + language which may be unfamiliar to you; + +- People who identify with a certain sexual orientation or gender + identity may use distinct names, or pronouns; + +- People having a particular physical or mental disability may use + particular terms to describe themselves + +- **Welcome everyone.** During in-person meetings, we will be + welcoming to everyone and we will be mindful and respectful of each + others' preferences, boundaries, sensibilities, traditions, and + requirements. + +### Civility, Collegiality, Mutual Support and Good Citizenship + +This includes but is not limited to: + +- **Mentorship and coaching.** Helping newcomers to find their way and + acquire essential skills. + +- **Looking out for fellow community members.** Lending them a hand + when they need support, and speaking up for them when they are + treated in a way that falls short of expected behaviour as per the + Code of Conduct. + +- **Recognise and credit the work done by contributors.** Thanking + them for their help and work. Appreciating their efforts and give + credit where it is due. + +Unacceptable Behaviour +---------------------- + +We are a community of professionals, and we conduct ourselves +professionally. Be kind and respectful to others. Do not insult or put +down other participants. Public or private harassment and other types of +exclusionary behaviour are not acceptable. + +**Examples of unacceptable behaviour include, but are not limited to:** + +- Written or verbal comments which have the effect of excluding people + on the basis of membership of any specific group; + +- Causing someone to fear for their safety, such as through stalking, + following, or other forms of intimidation; + +- Non-consensual or unwelcome physical contact; + +- Sustained disruption of talks, events, or communications; + +- Excessive swearing; + +- Incitement to violence, suicide, or self-harm; + +- Insults or put downs; + +- Violent threats or language directed against another person; + +- Discriminatory jokes and language (e.g., sexist, racist, homophobic, + transphobic, ableist, or exclusionary jokes); + +- Posting sexually explicit or violent material; + +- Trolling, insulting, or derogatory comments, and personal or + political attacks; + +- Publishing (or threatening to publish) other people\'s personally + identifying information, such as physical or digital information + without reasonable project or work-specific relevancy (\"doxing\"); + +- Continuing to initiate interaction (including photography or + recording) with someone after being asked to stop; + +- Repeated public or private harassment (further details see below) of + others. In general, if someone asks you to stop, then stop; + +- Publication of private communication without consent; + +- Personal insults, especially those using racist or sexist terms; + +- Unwelcome sexual attention; + +- The use of sexualised language or imagery, sexual attention, or + sexual advances of any kind; + +- Advocating for, or encouraging, any of the above behaviour. + +Disagreements, both social and technical, happen all the time. It is +important that we resolve disagreements and differing views +constructively. Remember that we are different. The strength of COPIM +comes from its varied community, inclusive of people from a wide range +of backgrounds. Different people have different perspectives on issues. +Being unable to understand why someone holds a viewpoint does not mean +that they are wrong. Don't forget that it is human to err, and blaming +each other does not get us anywhere. Instead, focus on collectively +helping to resolve issues and learning from mistakes. + +### Harassment + +This includes any behaviour intended primarily to intimidate, outrage, +or upset a person, or any behaviour where this would reasonably be +considered the most likely main outcome. Behaviour can be considered +harassment if it is beyond what a reasonable person would be expected to +tolerate in a global, intercultural environment. Harassment often takes +the form of emotional abuse, especially towards people who are in a +vulnerable position, and may include contacting workplaces or friends +and family members in an effort to intimidate or embarrass someone. In +some cases, behaviour that would not rise to the level of harassment in +a single case can become harassment through repetition. + +**Harassment includes but is not limited to:** + +- **Insults.** This includes name calling, using slurs or stereotypes, + and any attacks based on personal characteristics. Insults may refer + to perceived characteristics like intelligence, appearance, + ethnicity, race, religion (or lack thereof), culture, caste, sexual + orientation, gender, sex, disability, age, nationality, political + affiliation, or other identity characteristics. In some cases, + repeated mockery, sarcasm, or aggression constitute insults + collectively, even if individual statements would not; + +- **Sexual harassment.** Sexual attention or advances of any kind + towards others where the person knows or reasonably should know that + the attention is unwelcome or in situations where consent cannot be + communicated; + +- **Threats.** Explicitly or implicitly suggesting the possibility of + physical violence, unfair embarrassment, unfair and unjustified + reputational harm, or intimidation by suggesting gratuitous legal + action to win an argument or force someone to behave the way you + want; + +- **Encouraging harm to others.** This includes encouraging someone + else to commit self-harm or suicide as well as encouraging someone + to conduct violent attacks on a third party; + +- **Disclosure of personal data (Doxing).** Sharing other + contributors\' private information, such as name, place of + employment, physical or email address without their explicit consent + either on COPIM projects or elsewhere, or sharing information + concerning their COPIM activity outside the projects; + +- **Hounding.** Following a person across the project(s) and + repeatedly critiquing their work mainly with the intent to upset or + discourage them; + +- **Trolling.** Deliberately disrupting conversations or posting in + bad-faith to intentionally provoke. + +### Abuse of Power, Privilege, or Influence + +Abuse occurs when someone in a real or perceived position of power, +privilege, or influence engages in disrespectful, cruel, and/or violent +behaviour towards other people. In COPIM environments, it may take the +form of verbal or psychological abuse and may overlap with harassment. +This includes: + +- **Abuse of office by functionaries, officials and staff.** The use + of authority, knowledge, or resources at the disposal of designated + functionaries, to intimidate or threaten others; + +- **Abuse of seniority and connections.** Using one\'s position and + reputation to intimidate others. We expect people with significant + experience and connections in the movement to behave with special + care because hostile comments from them may carry an unintended + backlash. People with community authority have a particular + privilege to be viewed as reliable and should not abuse this + privilege to attack others who disagree with them; + +- **Psychological manipulation.** Maliciously causing someone to doubt + their own perceptions, senses, or understanding with the objective + to win an argument, or force someone to behave the way you want; + +Reporting Instructions +---------------------- + +**The COPIM  **[**Code of Conduct +Committee**](https://www.copim.ac.uk/governance/code-of-conduct/)** is +responsible for enforcing the Code of Conduct. It can be contacted by +emailing **[**conduct\@copim.ac.uk**](mailto:conduct@copim.ac.uk)**.** + +All reports will be reviewed by the Code of Conduct Committee according +to our Enforcement Guidelines (see +[underneath](#enforcement-guidelines)) and will be kept confidential. A +report guarantees review, but not necessarily that an action will be +taken. + +Code of Conduct Incident Reporting Guidelines +--------------------------------------------- + +If you are attending a COPIM workshop, in-person event, or participating +in one of our online events or communication channels and believe +someone is in physical danger, please ask your workshop host, or another +community member to contact the appropriate emergency responders +(police, crisis hotline, etc.). Prior to a COPIM workshop or in-person +or virtual event, event organisers should determine emergency contact +numbers and local procedures. + +If you believe someone violated the Code of Conduct during a COPIM event +or in a COPIM online space, we ask that you report it. If you are not +sure if the incident happened in a COPIM governed space, we ask that you +still report the incident. You are encouraged to submit your report by +emailing conduct (@) copim.ac.uk.  + +You may report anonymously, or you can include your contact information. +Your email to this address will be seen by all of the the COPIM Code of +Conduct Committee. If you are uncomfortable reporting to the Code of +Conduct committee, or if your report concerns a current member of the +Code of Conduct committee, incidents can also be reported to Tim +Elfenbein, the current Chair of the Code of Conduct committee, +separately at Tim\_Elfenbein (@) forthcoming.work. The Chair will follow +the usual enforcement process with the other committee members, but will +exclude the member(s) that the report concerns from any discussion or +decision making. If your report concerns the current Chair of the +committee, please send your report to any of the other [CoC Committee +members](https://www.copim.ac.uk/governance/code-of-conduct/), who will +follow the usual enforcement process with the other committee members, +but will exclude the Chair. + +You are welcome to report an incident anonymously. If you would like +someone to follow-up with you about the progress of your incident report +however, you would need to provide contact information. + +**All reports will be kept confidential** with details shared only with +the Code of Conduct committee members. In the case that a CoC committee +member is involved in a report, the member will be asked to recuse +themselves from ongoing conversations, and they will not have access to +reports after the enforcement decision has been made. Resolution action +may also include removal of that member from the CoC committee. + +Some incidents happen in one-on-one interactions, and though details are +anonymised, the reported person may be able to guess who made the +report. If you have concerns about retaliation or your personal safety, +please note those concerns in your report. You are still encouraged to +report the incident so that we can support you while keeping our +community members safe. In some cases, we can compile several anonymised +reports into a pattern of behaviour, and take action on that pattern. + +The Code of Conduct committee may determine that a public statement +should be made about the incident and/or the action taken. If that is +the case, the identities of all reporters and reportees will remain +confidential unless those individuals instruct the CoC committee +otherwise. + +**In your report please include:** + +- Your contact info (optional --- so we can get in touch with you if + we need to follow up); + +- Names (real, nicknames, or pseudonyms) of any individuals involved. + If there were other witnesses besides you, please try to include + them as well; + +- When and where the incident occurred. Please be as specific as + possible; + +- Your account of what occurred. If there is a publicly available + record (e.g. a mailing list archive) please include a link to that + record; + +- Any extra context you believe existed for the incident; + +- If you believe this incident is ongoing; + +- Any other information you believe we should have. + +### What happens after you file a report? + +Following Up with Reporter(s): Once a report is received from the email +address provided above, the Code of Conduct committee will handle the +review and follow up according to the procedures in the [Enforcement +Guidelines](#enforcement-guidelines). You will receive an email from the +CoC Committee acknowledging receipt immediately. We promise to +acknowledge receipt within 24 hours (and will aim for much quicker than +that). + +The Committee will immediately meet to review the incident and +determine: + +- What happened; + +- Whether this event constitutes a Code of Conduct violation; + +- Who the bad actor was; + +- Whether this is an isolated incident, an ongoing situation, or if + there is a threat to anyone\'s physical safety. + +The committee is empowered to act on COPIM\'s behalf in contacting any +individuals involved to get a more complete account of events. If this +is determined to be an ongoing incident or a threat to physical safety, +the working groups\' immediate priority will be to protect everyone +involved. This means we may delay an \"official\" response until we +believe that the situation has ended and that everyone is physically +safe. + +Once the Committee has a complete account of the events they will make a +decision as to how to respond. The committee should aim to have a +resolution agreed upon within one week. In the event that a resolution +can\'t be determined in that time, the committee will respond to the +reporter(s) with an update and projected timeline for resolution. Once +the committee has determined their final action, they will contact the +original reporter to let them know what action (if any) they will be +taking. They will take into account feedback from the reporter on the +appropriateness of their response, but they don\'t guarantee they will +act on it. Finally, the Committee will make a report on the situation to +the COPIM Project Group. The Project Group may choose to make a public +report of the incident. + +This information will be collected in writing, and whenever possible or +appropriate the committee\'s deliberations will be recorded and retained +(i.e. email discussions, recorded voice conversations, etc.). + +### Immediate Response + +Participants who are asked to stop any inappropriate behaviour are +expected to comply immediately. This applies to any COPIM events and +platforms, either online or in-person. If a participant engages in +behaviour that violates this code of conduct, the organisers may warn +the offender, ask them to leave the event or platform, or engage COPIM's +[Code of Conduct +Committee](https://www.copim.ac.uk/governance/code-of-conduct/) to +investigate the Code of Conduct violation and impose appropriate +sanctions. + +All COPIM community members should feel empowered to enforce the Code of +Conduct. Ideally, we would all be able to defuse an incident. In +practice, we have varying comfort with situations depending on our +current experience and the environment. Below are ways that you can be +supportive and steps that you can take during or after an incident. + +If you can, move from being a bystander to being a Code of Conduct first +responder. If you see something inappropriate happening, speak up. If +you don't feel comfortable intervening, but feel someone should, please +submit a report in person to a workshop host or instructor or via the +email address provided above to the Code of Conduct committee. + +Depending on the severity and/or details of the incident, an immediate +response may be required. If an incident involves physical danger or +involves a threat to anyone's safety (e.g. threats of violence), any +member of the community may -- and should -- act immediately to protect +the safety of others. This can include contacting emergency or crisis +resources. + +### Immediate Response Checklist + +- Assess whether you need a first-responder (law enforcement, etc.) to + immediately respond to the incident. If so, ask the reporter to stay + with you and dial the appropriate emergency response number; + +- If there is any general threat to participants and/or the safety of + anyone attending a COPIM event, contact the emergency response + number established; + +- If individuals are physically safe, contact law enforcement or + security only at the reporter's request; + +- Follow any local guidelines for handling incidents, including if you + have a legal reporting role; + +Individuals reported often get upset, defensive, or deny the report. +Allow them to give any additional details about the incident. However, +remember: + +- It does not matter if they did not intend to hurt anyone; their + behaviour still impacted participants negatively; + +- It is not your job to reassure or forgive them; + +- Do not allow the reported person to make an apology to the reporter + or impacted person.\ + Often an apology centres the reported person's feelings and not the + person who was impacted. You may accept their apology and offer to + pass it on, but you're not required to if you think it would + negatively impact the reporter. + +Enforcement Guidelines +---------------------- + +All responses to reports of conduct violations will be managed by the +COPIM [Code of Conduct +Committee](https://www.copim.ac.uk/governance/code-of-conduct/). This +section outlines the Incident Response Procedure and Enforcement +Guidelines followed by the COPIM Code of Conduct Committee once an +incident report is received by emailing conduct (@) copim.ac.uk. + +These guidelines are used when the Committee reviews and resolves +incidents to ensure consistency, transparency, and fairness. + +The COPIM Project Group will establish this committee, comprised of at +least three members. One member will be designated Chair of the +committee and will be responsible for all reports back to the Project +Group. The Project Group will review membership on a regular basis. + +Resolutions +----------- + +The committee must agree on a resolution by the majority of all members +investigating the incident in question. If the committee cannot reach a +majority decision and deadlocks for over one week, they will turn the +matter over to the COPIM PIs for resolution. + +What follows are examples of possible resolutions to an incident report. +This list is not comprehensive, and the COPIM Code of Conduct Committee +reserves the right to take any action it deems necessary to resolve an +incident. Possible resolutions to an incident include: + +- Taking no further action, if the Code of Conduct committee + determined there was no breach in the Code of Conduct; + +- A private verbal reprimand from the committee/a committee member to + the individual(s) involved. This conversation may happen in person, + over video conference call, or by phone. The committee/a committee + member will write a short report of the conversation to be shared + with the reportee for verification purposes and then shared with the + Committee and maintained on record in a private CoC Committee folder + on the COPIM Nextcloud; + +- A private emailed reprimand from the committee or a committee member + to the individual(s) involved providing clarity around the nature of + the violation and an explanation of why the behaviour was + inappropriate. The committee/a committee member  will deliver a + reprimand to the individual(s) over email, cc'ing the Code of + Conduct Committee; + +- A public announcement of an incident. In this case, a committee + member will deliver that reprimand ideally in the same venue that + the violation occurred (e.g., on Mattermost for a Mattermost + violation). The Committee may choose to publish this message + elsewhere for posterity; + +- An imposed suspension (i.e., asking someone to "take a week off" + from COPIM meetings and communication channels). The Committee/a + committee member will communicate this suspension to the reportee. + The suspension includes no interaction with the people involved, + including unsolicited interaction with those enforcing the Code of + Conduct, for a specified period of time. The reportee will be asked + to take this suspension voluntarily, but if they do not agree, then + a temporary ban may be imposed to enforce this suspension. + +- A permanent or temporary ban from some or all COPIM spaces + (Mattermost, NextCloud, workshops and meetings, etc.) The CoC + committee will maintain records of all such bans so that they may be + reviewed in the future, extended to new communication forums, or + otherwise maintained. + +- A request for a public or private apology. A committee member will + deliver this request. The committee may, if it chooses, attach + \"strings\" to this request: for example, the committee may ask a + violator to apologise in order to retain their membership on a + mailing list. + +### **During a workshop/conference or event** + +- Requiring that the reportee avoid any interaction with, and physical + proximity to, another person for the remainder of the COPIM event; + +- Ending a talk that violates the Code of Conduct early; + +- Not publishing the video or slides of a talk that violated the Code + of Conduct; + +- Not allowing a speaker who violated the Code of Conduct to give + (further) talks at COPIM workshops or events now or in the future; + +- Requiring that the reportee not volunteer for future COPIM events + either indefinitely or for a certain time period determined by the + Committee; + +- Requiring that the reportee refund any travel grant funding they + received; + +- Requiring that the reportee immediately leave an event and not + return; + +- Immediately ending any volunteer responsibilities and privileges the + reportee holds. + +Following up with the Reporter and Reportee +------------------------------------------- + +Once a resolution is agreed upon, but before it is enacted, the +committee will contact the original reporter and any other affected +parties and explain the proposed resolution. The committee will ask if +this resolution is acceptable, and must note feedback for the record. +However, the committee is not required to act on this feedback. + +When following up with the reportee, the CoC Committee representatives +will: + +- Explain that an incident was reported that involves the reportee; In + this explanation, the focus will be on the impact of their + behaviour, not their intent; + +- Reiterate the Code of Conduct and that their behaviour was deemed + inappropriate; + +- Provide concrete examples of how they can improve their behaviour; + +- Give them the opportunity to state their view of the incident; + +- Remind them of the consequences of their behaviour, or future + consequences if the behaviour is repeated; + +- Explain the possible resolutions that may be enforced should the + Committee determine there is a breach. + +Finally the Committee will make a report for the COPIM Project Group in +the event of an ongoing resolution, such as a termed suspension or ban. +In case the incident or report involves a current member of the COPIM +Project Group, the committee will provide the report only to the other +Project Group members. The Committee will never publicly discuss the +issue; all public statements will be made by the COPIM Project Group. + +Appeal Process +-------------- + +Any individual(s) involved in a Code of Conduct report handled by CoC +committee has the right to appeal a decision made by the committee. An +appeal can be made directly to the Committee (email: conduct (@) +copim.ac.uk) or to the Chair (email: Tim\_Elfenbein (@) +forthcoming.work) by sending an email with the subject line **Code of +Conduct Incident Appeal**. Appeals can be requested up to 30 days after +a resolution has been determined. + +The email should include documentation related to the incident to +support the appeal. The said documentation may include, but does not +have to be limited to: + +- Information from the reportee justifying the reasoning for the + appeal; + +- Letters of support from community members; + +- Statements from other individuals involved in the incident to + support the appeal. + + Accountability +--------------- + +The CoC committee will submit a report to the COPIM Project Group in the +event of an ongoing resolution, such as a termed suspension or ban. + +At the end of every year, the COPIM Project Group will publish an +aggregated count of the incidents the Code of Conduct Committee has +reviewed, indicating how many reports it received, how many incidents it +investigated independently, how many times it acted unilaterally, and, +for each of these, under which part of the Code of Conduct the incident +was classified. + +Conflicts of Interest +--------------------- + +In the event of any conflict of interest (a committee member, their +family member, or someone with whom the committee member has a close +academic or employment relationship is involved in a complaint), the +committee member must immediately notify the other members and recuse +themselves if necessary. + +In the case that a CoCc member is involved in a report, the member will +be asked to recuse themselves from ongoing conversations, and they will +not have access to reports after the enforcement decision has been made. +Resolution action may also include removal of that member from the Code +of Conduct committee. + +Update Logs +----------- + +This CoC was first published on Friday May 28th 2021 + +Subsequent edits will be documented in this section. + +About this Document +------------------- + +This document is adapted from guidelines written by + +- **Contributor Covenant**:   + +- **The Carpentries CoC + library:**   + +- **Wikimedia**: + + +- **Django Project**:  which + was itself based on the [Ada + Initiative](https://adainitiative.org/) template and the [PyCon 2013 + Procedure for Handling Harassment + Incidents](https://us.pycon.org/2013/about/code-of-conduct/harassment-incidents/). + +- **The Speak Up! project**: + + + We further consulted: + +- **Geek Feminism:** Overview and comparison of different codes of + conduct within open source projects: + + +- **Open Source Guide:** + +- **Ada Initiative**: + + +  + +***Contributors*** to the initial document are Janneke Adema, Eileen +Joy, Samuel Moore, Tobias Steiner, and Lidia Uziel. + diff --git a/Cargo.lock b/Cargo.lock index 3863ac67c..0bec447ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3936,7 +3936,7 @@ dependencies = [ [[package]] name = "thoth" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cargo-husky", "clap", @@ -3951,7 +3951,7 @@ dependencies = [ [[package]] name = "thoth-api" -version = "0.7.1" +version = "0.7.2" dependencies = [ "actix-web", "argon2rs", @@ -3980,7 +3980,7 @@ dependencies = [ [[package]] name = "thoth-api-server" -version = "0.7.1" +version = "0.7.2" dependencies = [ "actix-cors", "actix-identity", @@ -3995,7 +3995,7 @@ dependencies = [ [[package]] name = "thoth-app" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "chrono", @@ -4018,7 +4018,7 @@ dependencies = [ [[package]] name = "thoth-app-server" -version = "0.7.1" +version = "0.7.2" dependencies = [ "actix-cors", "actix-web", @@ -4027,7 +4027,7 @@ dependencies = [ [[package]] name = "thoth-client" -version = "0.7.1" +version = "0.7.2" dependencies = [ "chrono", "graphql_client", @@ -4041,7 +4041,7 @@ dependencies = [ [[package]] name = "thoth-errors" -version = "0.7.1" +version = "0.7.2" dependencies = [ "actix-web", "csv", @@ -4056,7 +4056,7 @@ dependencies = [ [[package]] name = "thoth-export-server" -version = "0.7.1" +version = "0.7.2" dependencies = [ "actix-cors", "actix-web", diff --git a/Cargo.toml b/Cargo.toml index 890338d61..02ab2ca8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -16,11 +16,11 @@ maintenance = { status = "actively-developed" } members = ["thoth-api", "thoth-api-server", "thoth-app", "thoth-app-server", "thoth-client", "thoth-errors", "thoth-export-server"] [dependencies] -thoth-api = { version = "0.7.1", path = "thoth-api", features = ["backend"] } -thoth-api-server = { version = "0.7.1", path = "thoth-api-server" } -thoth-app-server = { version = "0.7.1", path = "thoth-app-server" } -thoth-errors = { version = "0.7.1", path = "thoth-errors" } -thoth-export-server = { version = "0.7.1", path = "thoth-export-server" } +thoth-api = { version = "0.7.2", path = "thoth-api", features = ["backend"] } +thoth-api-server = { version = "0.7.2", path = "thoth-api-server" } +thoth-app-server = { version = "0.7.2", path = "thoth-app-server" } +thoth-errors = { version = "0.7.2", path = "thoth-errors" } +thoth-export-server = { version = "0.7.2", path = "thoth-export-server" } clap = "2.33.3" dialoguer = "0.7.1" dotenv = "0.9.0" diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 000000000..09ea40e50 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,28 @@ +# Support + +## Thoth wiki +The Thoth team actively contributes to its [Wiki](../../wiki), if you have a question about book metadata we might have an entry about it. + +Our wiki also includes the [Thoth User Manual](../../wiki/Thoth-User-Manual). + +## Asking quality questions +> This section has been borrowed from Titus Wormer's [remarkjs support document](https://github.com/remarkjs/.github/blob/main/support.md) + +Questions can go to [GitHub discussions](https://github.com/thoth-pub/thoth/discussions). + +Help us help you! +Spend time framing questions and add links and resources. +Spending the extra time up front can help save everyone time in the long run. +Here are some tips: + +* [Talk to a duck](https://rubberduckdebugging.com)! +* Don’t fall for the [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378) +* Search to find out if a similar question has been asked +* Try to define what you need help with: + * Is there something in particular you want to do? + * What problem are you encountering and what steps have you taken to try + and fix it? + * Is there a concept you don’t understand? +* Screenshots can help, but if there’s important text such as code or error + messages in them, please also provide those as text +* The more time you put into asking your question, the better we can help you diff --git a/thoth-api-server/Cargo.toml b/thoth-api-server/Cargo.toml index 0edaa86a6..69c31cf75 100644 --- a/thoth-api-server/Cargo.toml +++ b/thoth-api-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-api-server" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -9,8 +9,8 @@ repository = "https://github.com/thoth-pub/thoth" readme = "README.md" [dependencies] -thoth-api = { version = "0.7.1", path = "../thoth-api", features = ["backend"] } -thoth-errors = { version = "0.7.1", path = "../thoth-errors" } +thoth-api = { version = "0.7.2", path = "../thoth-api", features = ["backend"] } +thoth-errors = { version = "0.7.2", path = "../thoth-errors" } actix-web = "3.3.2" actix-cors = "0.5.4" actix-identity = "0.3.1" diff --git a/thoth-api/Cargo.toml b/thoth-api/Cargo.toml index 5566f3ae8..b826e7579 100644 --- a/thoth-api/Cargo.toml +++ b/thoth-api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-api" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -16,7 +16,7 @@ maintenance = { status = "actively-developed" } backend = ["diesel", "diesel-derive-enum", "diesel_migrations", "futures", "actix-web"] [dependencies] -thoth-errors = { version = "0.7.1", path = "../thoth-errors" } +thoth-errors = { version = "0.7.2", path = "../thoth-errors" } actix-web = { version = "3.3.2", optional = true } argon2rs = "0.2.5" isbn2 = "0.4.0" diff --git a/thoth-api/migrations/0.7.2/down.sql b/thoth-api/migrations/0.7.2/down.sql new file mode 100644 index 000000000..a8cd1a3a4 --- /dev/null +++ b/thoth-api/migrations/0.7.2/down.sql @@ -0,0 +1,20 @@ +ALTER TABLE series + DROP COLUMN series_description, + DROP COLUMN series_cfp_url; + +-- We cannot drop individual enum values - we must drop the type and recreate it +-- +-- Delete publications with about-to-be-dropped types +DELETE FROM publication WHERE publication_type IN ('AZW3', 'DOCX', 'FictionBook'); +ALTER TABLE publication ALTER publication_type TYPE text; +DROP TYPE publication_type; +CREATE TYPE publication_type AS ENUM ( + 'Paperback', + 'Hardback', + 'PDF', + 'HTML', + 'XML', + 'Epub', + 'Mobi' +); +ALTER TABLE publication ALTER publication_type TYPE publication_type USING publication_type::publication_type; diff --git a/thoth-api/migrations/0.7.2/up.sql b/thoth-api/migrations/0.7.2/up.sql new file mode 100644 index 000000000..0a63bab4a --- /dev/null +++ b/thoth-api/migrations/0.7.2/up.sql @@ -0,0 +1,9 @@ +ALTER TABLE series + -- Description of the series + ADD COLUMN series_description TEXT CHECK (octet_length(series_description) >= 1), + -- Call for proposals URL + ADD COLUMN series_cfp_url TEXT CHECK (series_cfp_url ~* '^[^:]*:\/\/(?:[^\/:]*:[^\/@]*@)?(?:[^\/:.]*\.)+([^:\/]+)'); + +ALTER TYPE publication_type ADD VALUE IF NOT EXISTS 'AZW3'; +ALTER TYPE publication_type ADD VALUE IF NOT EXISTS 'DOCX'; +ALTER TYPE publication_type ADD VALUE IF NOT EXISTS 'FictionBook'; diff --git a/thoth-api/src/graphql/model.rs b/thoth-api/src/graphql/model.rs index 06b56882a..9f68ccf49 100644 --- a/thoth-api/src/graphql/model.rs +++ b/thoth-api/src/graphql/model.rs @@ -744,7 +744,7 @@ impl QueryRoot { offset(default = 0, description = "The number of items to skip"), filter( default = "".to_string(), - description = "A query string to search. This argument is a test, do not rely on it. At present it simply searches for case insensitive literals on series_name, issn_print, issn_digital and series_url" + description = "A query string to search. This argument is a test, do not rely on it. At present it simply searches for case insensitive literals on series_name, issn_print, issn_digital, series_url and series_description" ), order( default = SeriesOrderBy::default(), @@ -794,7 +794,7 @@ impl QueryRoot { arguments( filter( default = "".to_string(), - description = "A query string to search. This argument is a test, do not rely on it. At present it simply searches for case insensitive literals on series_name, issn_print, issn_digital and series_url", + description = "A query string to search. This argument is a test, do not rely on it. At present it simply searches for case insensitive literals on series_name, issn_print, issn_digital, series_url and series_description", ), publishers( default = vec![], @@ -2921,10 +2921,20 @@ impl Series { &self.issn_digital } + #[graphql(description = "URL of the series' landing page")] pub fn series_url(&self) -> Option<&String> { self.series_url.as_ref() } + pub fn series_description(&self) -> Option<&String> { + self.series_description.as_ref() + } + + #[graphql(description = "URL of the series' call for proposals page")] + pub fn series_cfp_url(&self) -> Option<&String> { + self.series_cfp_url.as_ref() + } + pub fn imprint_id(&self) -> Uuid { self.imprint_id } diff --git a/thoth-api/src/model/publication/mod.rs b/thoth-api/src/model/publication/mod.rs index 4bd8a8222..c3e7e7e8f 100644 --- a/thoth-api/src/model/publication/mod.rs +++ b/thoth-api/src/model/publication/mod.rs @@ -36,6 +36,14 @@ pub enum PublicationType { Epub, #[cfg_attr(feature = "backend", db_rename = "Mobi")] Mobi, + #[cfg_attr(feature = "backend", db_rename = "AZW3")] + #[strum(serialize = "AZW3")] + Azw3, + #[cfg_attr(feature = "backend", db_rename = "DOCX")] + #[strum(serialize = "DOCX")] + Docx, + #[cfg_attr(feature = "backend", db_rename = "FictionBook")] + FictionBook, } #[cfg_attr( @@ -171,6 +179,9 @@ fn test_publicationtype_display() { assert_eq!(format!("{}", PublicationType::Xml), "XML"); assert_eq!(format!("{}", PublicationType::Epub), "Epub"); assert_eq!(format!("{}", PublicationType::Mobi), "Mobi"); + assert_eq!(format!("{}", PublicationType::Azw3), "AZW3"); + assert_eq!(format!("{}", PublicationType::Docx), "DOCX"); + assert_eq!(format!("{}", PublicationType::FictionBook), "FictionBook"); } #[test] @@ -214,9 +225,23 @@ fn test_publicationtype_fromstr() { PublicationType::from_str("Mobi").unwrap(), PublicationType::Mobi ); + assert_eq!( + PublicationType::from_str("AZW3").unwrap(), + PublicationType::Azw3 + ); + assert_eq!( + PublicationType::from_str("DOCX").unwrap(), + PublicationType::Docx + ); + assert_eq!( + PublicationType::from_str("FictionBook").unwrap(), + PublicationType::FictionBook + ); assert!(PublicationType::from_str("PNG").is_err()); assert!(PublicationType::from_str("Latex").is_err()); + assert!(PublicationType::from_str("azw3").is_err()); + assert!(PublicationType::from_str("Fiction Book").is_err()); } #[test] diff --git a/thoth-api/src/model/series/crud.rs b/thoth-api/src/model/series/crud.rs index 163d744b7..8ee5b6db5 100644 --- a/thoth-api/src/model/series/crud.rs +++ b/thoth-api/src/model/series/crud.rs @@ -50,6 +50,8 @@ impl Crud for Series { imprint_id, created_at, updated_at, + series_description, + series_cfp_url, )) .into_boxed(); @@ -78,6 +80,14 @@ impl Crud for Series { Direction::Asc => query = query.order(series_url.asc()), Direction::Desc => query = query.order(series_url.desc()), }, + SeriesField::SeriesDescription => match order.direction { + Direction::Asc => query = query.order(series_description.asc()), + Direction::Desc => query = query.order(series_description.desc()), + }, + SeriesField::SeriesCfpUrl => match order.direction { + Direction::Asc => query = query.order(series_cfp_url.asc()), + Direction::Desc => query = query.order(series_cfp_url.desc()), + }, SeriesField::CreatedAt => match order.direction { Direction::Asc => query = query.order(created_at.asc()), Direction::Desc => query = query.order(created_at.desc()), @@ -99,7 +109,8 @@ impl Crud for Series { .ilike(format!("%{}%", filter)) .or(issn_print.ilike(format!("%{}%", filter))) .or(issn_digital.ilike(format!("%{}%", filter))) - .or(series_url.ilike(format!("%{}%", filter))), + .or(series_url.ilike(format!("%{}%", filter))) + .or(series_description.ilike(format!("%{}%", filter))), ); } match query @@ -136,7 +147,8 @@ impl Crud for Series { .ilike(format!("%{}%", filter)) .or(issn_print.ilike(format!("%{}%", filter))) .or(issn_digital.ilike(format!("%{}%", filter))) - .or(series_url.ilike(format!("%{}%", filter))), + .or(series_url.ilike(format!("%{}%", filter))) + .or(series_description.ilike(format!("%{}%", filter))), ); } diff --git a/thoth-api/src/model/series/mod.rs b/thoth-api/src/model/series/mod.rs index dcfd88bfc..dea5f882f 100644 --- a/thoth-api/src/model/series/mod.rs +++ b/thoth-api/src/model/series/mod.rs @@ -44,6 +44,9 @@ pub enum SeriesField { SeriesUrl, CreatedAt, UpdatedAt, + SeriesDescription, + #[strum(serialize = "SeriesCFPURL")] + SeriesCfpUrl, } #[cfg_attr(feature = "backend", derive(Queryable))] @@ -59,6 +62,8 @@ pub struct Series { pub imprint_id: Uuid, pub created_at: Timestamp, pub updated_at: Timestamp, + pub series_description: Option, + pub series_cfp_url: Option, } #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)] @@ -70,6 +75,8 @@ pub struct SeriesWithImprint { pub issn_print: String, pub issn_digital: String, pub series_url: Option, + pub series_description: Option, + pub series_cfp_url: Option, pub updated_at: Timestamp, pub imprint: ImprintWithPublisher, } @@ -85,6 +92,8 @@ pub struct NewSeries { pub issn_print: String, pub issn_digital: String, pub series_url: Option, + pub series_description: Option, + pub series_cfp_url: Option, pub imprint_id: Uuid, } @@ -101,6 +110,8 @@ pub struct PatchSeries { pub issn_print: String, pub issn_digital: String, pub series_url: Option, + pub series_description: Option, + pub series_cfp_url: Option, pub imprint_id: Uuid, } @@ -179,6 +190,11 @@ fn test_seriesfield_display() { assert_eq!(format!("{}", SeriesField::IssnPrint), "ISSNPrint"); assert_eq!(format!("{}", SeriesField::IssnDigital), "ISSNDigital"); assert_eq!(format!("{}", SeriesField::SeriesUrl), "SeriesURL"); + assert_eq!( + format!("{}", SeriesField::SeriesDescription), + "SeriesDescription" + ); + assert_eq!(format!("{}", SeriesField::SeriesCfpUrl), "SeriesCFPURL"); assert_eq!(format!("{}", SeriesField::CreatedAt), "CreatedAt"); assert_eq!(format!("{}", SeriesField::UpdatedAt), "UpdatedAt"); } @@ -223,6 +239,14 @@ fn test_seriesfield_fromstr() { SeriesField::from_str("SeriesURL").unwrap(), SeriesField::SeriesUrl ); + assert_eq!( + SeriesField::from_str("SeriesDescription").unwrap(), + SeriesField::SeriesDescription + ); + assert_eq!( + SeriesField::from_str("SeriesCFPURL").unwrap(), + SeriesField::SeriesCfpUrl + ); assert_eq!( SeriesField::from_str("CreatedAt").unwrap(), SeriesField::CreatedAt diff --git a/thoth-api/src/schema.rs b/thoth-api/src/schema.rs index 5ec73661e..f8653a808 100644 --- a/thoth-api/src/schema.rs +++ b/thoth-api/src/schema.rs @@ -367,6 +367,8 @@ table! { imprint_id -> Uuid, created_at -> Timestamptz, updated_at -> Timestamptz, + series_description -> Nullable, + series_cfp_url -> Nullable, } } diff --git a/thoth-app-server/Cargo.toml b/thoth-app-server/Cargo.toml index 52bf3eaa6..7d40f1cfd 100644 --- a/thoth-app-server/Cargo.toml +++ b/thoth-app-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-app-server" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" diff --git a/thoth-app/Cargo.toml b/thoth-app/Cargo.toml index bd69a69c4..4c0cb6ea8 100644 --- a/thoth-app/Cargo.toml +++ b/thoth-app/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-app" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -33,5 +33,5 @@ serde = { version = "1.0.115", features = ["derive"] } serde_json = "1.0" url = "2.1.1" uuid = { version = "0.7", features = ["serde", "v4"] } -thoth-api = { version = "0.7.1", path = "../thoth-api" } -thoth-errors = { version = "0.7.1", path = "../thoth-errors" } +thoth-api = { version = "0.7.2", path = "../thoth-api" } +thoth-errors = { version = "0.7.2", path = "../thoth-errors" } diff --git a/thoth-app/manifest.json b/thoth-app/manifest.json index a6be5b6e3..104bd3017 100644 --- a/thoth-app/manifest.json +++ b/thoth-app/manifest.json @@ -9,7 +9,7 @@ "start_url": "/?homescreen=1", "background_color": "#ffffff", "theme_color": "#ffdd57", - "version": "0.7.1", + "version": "0.7.2", "icons": [ { "src": "\/android-icon-36x36.png", diff --git a/thoth-app/src/component/new_series.rs b/thoth-app/src/component/new_series.rs index 4b2acf15b..ee2fbb576 100644 --- a/thoth-app/src/component/new_series.rs +++ b/thoth-app/src/component/new_series.rs @@ -23,6 +23,7 @@ use crate::agent::notification_bus::Request; use crate::component::utils::FormImprintSelect; use crate::component::utils::FormSeriesTypeSelect; use crate::component::utils::FormTextInput; +use crate::component::utils::FormTextarea; use crate::component::utils::FormUrlInput; use crate::models::imprint::imprints_query::FetchActionImprints; use crate::models::imprint::imprints_query::FetchImprints; @@ -74,6 +75,8 @@ pub enum Msg { ChangeIssnPrint(String), ChangeIssnDigital(String), ChangeSeriesUrl(String), + ChangeSeriesDescription(String), + ChangeSeriesCfpUrl(String), ChangeRoute(AppRoute), } #[derive(Clone, Properties)] @@ -195,6 +198,8 @@ impl Component for NewSeriesComponent { issn_print: self.series.issn_print.clone(), issn_digital: self.series.issn_digital.clone(), series_url: self.series.series_url.clone(), + series_description: self.series.series_description.clone(), + series_cfp_url: self.series.series_cfp_url.clone(), imprint_id: self.series.imprint_id, }, ..Default::default() @@ -222,6 +227,13 @@ impl Component for NewSeriesComponent { .issn_digital .neq_assign(issn_digital.trim().to_owned()), Msg::ChangeSeriesUrl(value) => self.series.series_url.neq_assign(value.to_opt_string()), + Msg::ChangeSeriesDescription(value) => self + .series + .series_description + .neq_assign(value.to_opt_string()), + Msg::ChangeSeriesCfpUrl(value) => { + self.series.series_cfp_url.neq_assign(value.to_opt_string()) + } Msg::ChangeRoute(r) => { let route = Route::from(r); self.router.send(RouteRequest::ChangeRoute(route)); @@ -306,6 +318,16 @@ impl Component for NewSeriesComponent { value=self.series.series_url.clone() oninput=self.link.callback(|e: InputData| Msg::ChangeSeriesUrl(e.value)) /> + +
diff --git a/thoth-app/src/component/series.rs b/thoth-app/src/component/series.rs index 8a730f628..bf054ec12 100644 --- a/thoth-app/src/component/series.rs +++ b/thoth-app/src/component/series.rs @@ -24,6 +24,7 @@ use crate::component::delete_dialogue::ConfirmDeleteComponent; use crate::component::utils::FormImprintSelect; use crate::component::utils::FormSeriesTypeSelect; use crate::component::utils::FormTextInput; +use crate::component::utils::FormTextarea; use crate::component::utils::FormUrlInput; use crate::component::utils::Loader; use crate::models::imprint::imprints_query::FetchActionImprints; @@ -93,6 +94,8 @@ pub enum Msg { ChangeIssnPrint(String), ChangeIssnDigital(String), ChangeSeriesUrl(String), + ChangeSeriesDescription(String), + ChangeSeriesCfpUrl(String), ChangeRoute(AppRoute), } @@ -264,6 +267,8 @@ impl Component for SeriesComponent { issn_print: self.series.issn_print.clone(), issn_digital: self.series.issn_digital.clone(), series_url: self.series.series_url.clone(), + series_description: self.series.series_description.clone(), + series_cfp_url: self.series.series_cfp_url.clone(), imprint_id: self.series.imprint.imprint_id, }, ..Default::default() @@ -339,6 +344,13 @@ impl Component for SeriesComponent { .issn_digital .neq_assign(issn_digital.trim().to_owned()), Msg::ChangeSeriesUrl(value) => self.series.series_url.neq_assign(value.to_opt_string()), + Msg::ChangeSeriesDescription(value) => self + .series + .series_description + .neq_assign(value.to_opt_string()), + Msg::ChangeSeriesCfpUrl(value) => { + self.series.series_cfp_url.neq_assign(value.to_opt_string()) + } Msg::ChangeRoute(r) => { let route = Route::from(r); self.router.send(RouteRequest::ChangeRoute(route)); @@ -433,6 +445,16 @@ impl Component for SeriesComponent { value=self.series.series_url.clone() oninput=self.link.callback(|e: InputData| Msg::ChangeSeriesUrl(e.value)) /> + +
diff --git a/thoth-app/src/models/series/create_series_mutation.rs b/thoth-app/src/models/series/create_series_mutation.rs index 0df6e64ff..e1f15e75b 100644 --- a/thoth-app/src/models/series/create_series_mutation.rs +++ b/thoth-app/src/models/series/create_series_mutation.rs @@ -11,6 +11,8 @@ const CREATE_SERIES_MUTATION: &str = " $issnPrint: String!, $issnDigital: String!, $seriesUrl: String, + $seriesDescription: String, + $seriesCfpUrl: String, $imprintId: Uuid! ) { createSeries(data: { @@ -19,6 +21,8 @@ const CREATE_SERIES_MUTATION: &str = " issnPrint: $issnPrint issnDigital: $issnDigital seriesUrl: $seriesUrl + seriesDescription: $seriesDescription + seriesCfpUrl: $seriesCfpUrl imprintId: $imprintId }){ seriesId @@ -52,6 +56,8 @@ pub struct Variables { pub issn_print: String, pub issn_digital: String, pub series_url: Option, + pub series_description: Option, + pub series_cfp_url: Option, pub imprint_id: Uuid, } diff --git a/thoth-app/src/models/series/series_query.rs b/thoth-app/src/models/series/series_query.rs index 6538d90d6..3b974bbf2 100644 --- a/thoth-app/src/models/series/series_query.rs +++ b/thoth-app/src/models/series/series_query.rs @@ -12,6 +12,8 @@ pub const SERIES_QUERY: &str = " issnPrint issnDigital seriesUrl + seriesDescription + seriesCfpUrl updatedAt imprint { imprintId diff --git a/thoth-app/src/models/series/update_series_mutation.rs b/thoth-app/src/models/series/update_series_mutation.rs index a2388c733..87842c3a5 100644 --- a/thoth-app/src/models/series/update_series_mutation.rs +++ b/thoth-app/src/models/series/update_series_mutation.rs @@ -12,6 +12,8 @@ const UPDATE_SERIES_MUTATION: &str = " $issnPrint: String!, $issnDigital: String!, $seriesUrl: String, + $seriesDescription: String, + $seriesCfpUrl: String, $imprintId: Uuid! ) { updateSeries(data: { @@ -21,6 +23,8 @@ const UPDATE_SERIES_MUTATION: &str = " issnPrint: $issnPrint issnDigital: $issnDigital seriesUrl: $seriesUrl + seriesDescription: $seriesDescription + seriesCfpUrl: $seriesCfpUrl imprintId: $imprintId }){ seriesId @@ -55,6 +59,8 @@ pub struct Variables { pub issn_print: String, pub issn_digital: String, pub series_url: Option, + pub series_description: Option, + pub series_cfp_url: Option, pub imprint_id: Uuid, } diff --git a/thoth-app/src/string.rs b/thoth-app/src/string.rs index 509a9e985..905b07625 100644 --- a/thoth-app/src/string.rs +++ b/thoth-app/src/string.rs @@ -40,7 +40,7 @@ strings! { EMPTY_PRICES => "This publication does not have any pricing information. Click above to add prices.", SEARCH_INSTITUTIONS => "Search by name, ROR ID or DOI", SEARCH_WORKS => "Search by title, DOI, internal reference, abstract or landing page", - SEARCH_SERIESES => "Search by series name, ISSN or URL", + SEARCH_SERIESES => "Search by series name, ISSN, URL or description", SEARCH_PUBLISHERS => "Search by publisher name or short name", SEARCH_IMPRINTS => "Search by imprint name or URL", SEARCH_CONTRIBUTORS => "Search by name or ORCID", diff --git a/thoth-client/Cargo.toml b/thoth-client/Cargo.toml index 35aeabc9c..de0216951 100644 --- a/thoth-client/Cargo.toml +++ b/thoth-client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-client" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -9,8 +9,8 @@ repository = "https://github.com/thoth-pub/thoth" readme = "README.md" [dependencies] -thoth-api = {version = "0.7.1", path = "../thoth-api" } -thoth-errors = {version = "0.7.1", path = "../thoth-errors" } +thoth-api = {version = "0.7.2", path = "../thoth-api" } +thoth-errors = {version = "0.7.2", path = "../thoth-errors" } graphql_client = "0.9.0" chrono = { version = "0.4", features = ["serde"] } reqwest = { version = "0.10", features = ["json"] } diff --git a/thoth-client/assets/queries.graphql b/thoth-client/assets/queries.graphql index 848a00fbb..4fde82dac 100644 --- a/thoth-client/assets/queries.graphql +++ b/thoth-client/assets/queries.graphql @@ -50,6 +50,8 @@ fragment Work on Work { issnPrint issnDigital seriesUrl + seriesDescription + seriesCfpUrl } } contributions { diff --git a/thoth-client/assets/schema.json b/thoth-client/assets/schema.json index ea38e6c49..6f53735e5 100644 --- a/thoth-client/assets/schema.json +++ b/thoth-client/assets/schema.json @@ -3756,6 +3756,30 @@ "ofType": null } }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "seriesDescription", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "seriesCfpUrl", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, { "args": [], "deprecationReason": null, @@ -7794,6 +7818,18 @@ "isDeprecated": false, "name": "SERIES_URL" }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "SERIES_DESCRIPTION" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "SERIES_CFP_URL" + }, { "deprecationReason": null, "description": null, @@ -17441,6 +17477,26 @@ "ofType": null } }, + { + "defaultValue": null, + "description": null, + "name": "seriesDescription", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "seriesCfpUrl", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, { "defaultValue": null, "description": null, @@ -20243,6 +20299,24 @@ "description": null, "isDeprecated": false, "name": "MOBI" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "AZW3" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "DOCX" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "FICTION_BOOK" } ], "fields": null, diff --git a/thoth-errors/Cargo.toml b/thoth-errors/Cargo.toml index e9db7fc23..4005017ef 100644 --- a/thoth-errors/Cargo.toml +++ b/thoth-errors/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-errors" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" diff --git a/thoth-export-server/Cargo.toml b/thoth-export-server/Cargo.toml index e22116c0c..379cfba55 100644 --- a/thoth-export-server/Cargo.toml +++ b/thoth-export-server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thoth-export-server" -version = "0.7.1" +version = "0.7.2" authors = ["Javier Arias ", "Ross Higman "] edition = "2018" license = "Apache-2.0" @@ -9,9 +9,9 @@ repository = "https://github.com/thoth-pub/thoth" readme = "README.md" [dependencies] -thoth-api = { version = "0.7.1", path = "../thoth-api" } -thoth-errors = { version = "0.7.1", path = "../thoth-errors" } -thoth-client = { version = "0.7.1", path = "../thoth-client" } +thoth-api = { version = "0.7.2", path = "../thoth-api" } +thoth-errors = { version = "0.7.2", path = "../thoth-errors" } +thoth-client = { version = "0.7.2", path = "../thoth-client" } actix-web = "3.3.2" actix-cors = "0.5.4" chrono = { version = "0.4", features = ["serde"] } diff --git a/thoth-export-server/src/csv/csv_thoth.rs b/thoth-export-server/src/csv/csv_thoth.rs index b59e4d0c9..4b993b9b3 100644 --- a/thoth-export-server/src/csv/csv_thoth.rs +++ b/thoth-export-server/src/csv/csv_thoth.rs @@ -64,7 +64,9 @@ struct CsvThothRow { rename = "publications [(type, isbn, [(ISO_4217_currency, price)], [(landing_page, full_text, platform, is_canonical)])]" )] publications: String, - #[serde(rename = "series [(type, name, issn_print, issn_digital, url, issue)]")] + #[serde( + rename = "series [(type, name, issn_print, issn_digital, url, cfp_url, description, issue)]" + )] series: String, #[serde(rename = "languages [(relation, ISO_639-3/B_language, is_main)]")] languages: String, @@ -326,7 +328,7 @@ impl CsvCell for WorkContributionsAffiliations { impl CsvCell for WorkIssues { fn csv_cell(&self) -> String { format!( - "(\"{:?}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\")", + "(\"{:?}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\")", self.series.series_type, self.series.series_name, self.series.issn_print, @@ -335,6 +337,14 @@ impl CsvCell for WorkIssues { .series_url .clone() .unwrap_or_else(|| "".to_string()), + self.series + .series_cfp_url + .clone() + .unwrap_or_else(|| "".to_string()), + self.series + .series_description + .clone() + .unwrap_or_else(|| "".to_string()), self.issue_ordinal, ) } @@ -466,6 +476,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: Some("https://www.series.com".to_string()), + series_description: Some("Description of series".to_string()), + series_cfp_url: Some("https://www.series.com/cfp".to_string()), }, }], contributions: vec![ @@ -667,8 +679,8 @@ mod tests { }; } - const TEST_RESULT: &str = r#""publisher","imprint","work_type","work_status","title","subtitle","edition","doi","publication_date","publication_place","license","copyright_holder","landing_page","width (mm)","width (cm)","width (in)","height (mm)","height (cm)","height (in)","page_count","page_breakdown","first_page","last_page","page_interval","image_count","table_count","audio_count","video_count","lccn","oclc","short_abstract","long_abstract","general_note","toc","cover_url","cover_caption","contributions [(type, first_name, last_name, full_name, orcid, [(position, ordinal, institution)])]","publications [(type, isbn, [(ISO_4217_currency, price)], [(landing_page, full_text, platform, is_canonical)])]","series [(type, name, issn_print, issn_digital, url, issue)]","languages [(relation, ISO_639-3/B_language, is_main)]","BIC [code]","THEMA [code]","BISAC [code]","LCC [code]","custom_categories [category]","keywords [keyword]","funding [(institution, institution_doi, ror, country, program, project, grant, jurisdiction)]","relations [(related_work, relation_type, ordinal)]" -"OA Editions","OA Editions Imprint","MONOGRAPH","ACTIVE","Book Title","Book Subtitle","1","10.00001/BOOK.0001","1999-12-31","León, Spain","http://creativecommons.org/licenses/by/4.0/","Author 1; Author 2","https://www.book.com","156.0","15.6","6.14","234.0","23.4","9.21","334","x+334","","","","15","20","25","30","123456789","987654321","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam ornare bibendum ex nec dapibus. Proin porta risus elementum odio feugiat tempus. Etiam eu felis ac metus viverra ornare. In consectetur neque sed feugiat ornare. Mauris at purus fringilla orci tincidunt pulvinar sed a massa. Nullam vestibulum posuere augue, sit amet tincidunt nisl pulvinar ac.","This is a general note","1. Chapter 1","https://www.book.com/cover","This is a cover caption","[(""AUTHOR"", ""Author"", ""1"", ""Author 1"", ""0000-0002-0000-0001"", [(""Manager"", ""1"", ""University of Life"")]),(""AUTHOR"", ""Author"", ""2"", ""Author 2"", """", )]","[(""PAPERBACK"", ""978-3-16-148410-0"", [(""EUR"", ""25.95""),(""GBP"", ""22.95""),(""USD"", ""31.95"")], [(""https://www.book.com/paperback"", """", ""OTHER"", ""true""),(""https://www.jstor.com/paperback"", """", ""JSTOR"", ""false"")]),(""HARDBACK"", ""978-1-4028-9462-6"", [(""EUR"", ""36.95""),(""GBP"", ""32.95""),(""USD"", ""40.95"")], ),(""PDF"", ""978-1-56619-909-4"", , [(""https://www.book.com/pdf_landing"", ""https://www.book.com/pdf_fulltext"", ""OTHER"", ""true"")]),(""HTML"", """", , [(""https://www.book.com/html_landing"", ""https://www.book.com/html_fulltext"", ""OTHER"", ""true"")]),(""XML"", ""978-92-95055-02-5"", , )]","[(""JOURNAL"", ""Name of series"", ""1234-5678"", ""8765-4321"", ""https://www.series.com"", ""1"")]","[(""ORIGINAL"", ""SPA"", ""true"")]","[""AAA"",""AAB""]","[""JWA""]","[""AAA000000"",""AAA000001""]","[""JA85""]","[""Category1""]","[""keyword1"",""keyword2""]","[(""Name of institution"", ""10.00001/INSTITUTION.0001"", ""0aaaaaa00"", ""MDA"", ""Name of program"", ""Name of project"", ""Number of grant"", ""Funding jurisdiction"")]","[(""Related work title"", ""HAS_CHILD"", ""1"")]" + const TEST_RESULT: &str = r#""publisher","imprint","work_type","work_status","title","subtitle","edition","doi","publication_date","publication_place","license","copyright_holder","landing_page","width (mm)","width (cm)","width (in)","height (mm)","height (cm)","height (in)","page_count","page_breakdown","first_page","last_page","page_interval","image_count","table_count","audio_count","video_count","lccn","oclc","short_abstract","long_abstract","general_note","toc","cover_url","cover_caption","contributions [(type, first_name, last_name, full_name, orcid, [(position, ordinal, institution)])]","publications [(type, isbn, [(ISO_4217_currency, price)], [(landing_page, full_text, platform, is_canonical)])]","series [(type, name, issn_print, issn_digital, url, cfp_url, description, issue)]","languages [(relation, ISO_639-3/B_language, is_main)]","BIC [code]","THEMA [code]","BISAC [code]","LCC [code]","custom_categories [category]","keywords [keyword]","funding [(institution, institution_doi, ror, country, program, project, grant, jurisdiction)]","relations [(related_work, relation_type, ordinal)]" +"OA Editions","OA Editions Imprint","MONOGRAPH","ACTIVE","Book Title","Book Subtitle","1","10.00001/BOOK.0001","1999-12-31","León, Spain","http://creativecommons.org/licenses/by/4.0/","Author 1; Author 2","https://www.book.com","156.0","15.6","6.14","234.0","23.4","9.21","334","x+334","","","","15","20","25","30","123456789","987654321","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.","Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum vel libero eleifend, ultrices purus vitae, suscipit ligula. Aliquam ornare quam et nulla vestibulum, id euismod tellus malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam ornare bibendum ex nec dapibus. Proin porta risus elementum odio feugiat tempus. Etiam eu felis ac metus viverra ornare. In consectetur neque sed feugiat ornare. Mauris at purus fringilla orci tincidunt pulvinar sed a massa. Nullam vestibulum posuere augue, sit amet tincidunt nisl pulvinar ac.","This is a general note","1. Chapter 1","https://www.book.com/cover","This is a cover caption","[(""AUTHOR"", ""Author"", ""1"", ""Author 1"", ""0000-0002-0000-0001"", [(""Manager"", ""1"", ""University of Life"")]),(""AUTHOR"", ""Author"", ""2"", ""Author 2"", """", )]","[(""PAPERBACK"", ""978-3-16-148410-0"", [(""EUR"", ""25.95""),(""GBP"", ""22.95""),(""USD"", ""31.95"")], [(""https://www.book.com/paperback"", """", ""OTHER"", ""true""),(""https://www.jstor.com/paperback"", """", ""JSTOR"", ""false"")]),(""HARDBACK"", ""978-1-4028-9462-6"", [(""EUR"", ""36.95""),(""GBP"", ""32.95""),(""USD"", ""40.95"")], ),(""PDF"", ""978-1-56619-909-4"", , [(""https://www.book.com/pdf_landing"", ""https://www.book.com/pdf_fulltext"", ""OTHER"", ""true"")]),(""HTML"", """", , [(""https://www.book.com/html_landing"", ""https://www.book.com/html_fulltext"", ""OTHER"", ""true"")]),(""XML"", ""978-92-95055-02-5"", , )]","[(""JOURNAL"", ""Name of series"", ""1234-5678"", ""8765-4321"", ""https://www.series.com"", ""https://www.series.com/cfp"", ""Description of series"", ""1"")]","[(""ORIGINAL"", ""SPA"", ""true"")]","[""AAA"",""AAB""]","[""JWA""]","[""AAA000000"",""AAA000001""]","[""JA85""]","[""Category1""]","[""keyword1"",""keyword2""]","[(""Name of institution"", ""10.00001/INSTITUTION.0001"", ""0aaaaaa00"", ""MDA"", ""Name of program"", ""Name of project"", ""Number of grant"", ""Funding jurisdiction"")]","[(""Related work title"", ""HAS_CHILD"", ""1"")]" "#; #[test] @@ -818,16 +830,20 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: Some("https://www.series.com".to_string()), + series_description: Some("Description of series".to_string()), + series_cfp_url: Some("https://www.series.com/cfp".to_string()), }, }; assert_eq!(CsvCell::::csv_cell(&issue), - r#"("JOURNAL", "Name of series", "1234-5678", "8765-4321", "https://www.series.com", "1")"#.to_string()); + r#"("JOURNAL", "Name of series", "1234-5678", "8765-4321", "https://www.series.com", "https://www.series.com/cfp", "Description of series", "1")"#.to_string()); issue.issue_ordinal = 2; issue.series.series_type = SeriesType::BOOK_SERIES; issue.series.series_url = None; + issue.series.series_description = Some("Different description".to_string()); + issue.series.series_cfp_url = None; assert_eq!( CsvCell::::csv_cell(&issue), - r#"("BOOK_SERIES", "Name of series", "1234-5678", "8765-4321", "", "2")"#.to_string() + r#"("BOOK_SERIES", "Name of series", "1234-5678", "8765-4321", "", "", "Different description", "2")"#.to_string() ); } diff --git a/thoth-export-server/src/csv/kbart_oclc.rs b/thoth-export-server/src/csv/kbart_oclc.rs index 659fcdee5..8fc11bd91 100644 --- a/thoth-export-server/src/csv/kbart_oclc.rs +++ b/thoth-export-server/src/csv/kbart_oclc.rs @@ -289,6 +289,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }, WorkIssues { @@ -299,6 +301,8 @@ mod tests { issn_print: "1111-2222".to_string(), issn_digital: "3333-4444".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }, ], diff --git a/thoth-export-server/src/xml/onix21_ebsco_host.rs b/thoth-export-server/src/xml/onix21_ebsco_host.rs index b4996a264..8da57740a 100644 --- a/thoth-export-server/src/xml/onix21_ebsco_host.rs +++ b/thoth-export-server/src/xml/onix21_ebsco_host.rs @@ -759,6 +759,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }; diff --git a/thoth-export-server/src/xml/onix3_jstor.rs b/thoth-export-server/src/xml/onix3_jstor.rs index 2d1771ea2..0f268b61b 100644 --- a/thoth-export-server/src/xml/onix3_jstor.rs +++ b/thoth-export-server/src/xml/onix3_jstor.rs @@ -726,6 +726,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }], contributions: vec![], diff --git a/thoth-export-server/src/xml/onix3_oapen.rs b/thoth-export-server/src/xml/onix3_oapen.rs index 51c652e66..510e11d36 100644 --- a/thoth-export-server/src/xml/onix3_oapen.rs +++ b/thoth-export-server/src/xml/onix3_oapen.rs @@ -782,6 +782,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }; diff --git a/thoth-export-server/src/xml/onix3_project_muse.rs b/thoth-export-server/src/xml/onix3_project_muse.rs index c1ec7dbce..8051077a1 100644 --- a/thoth-export-server/src/xml/onix3_project_muse.rs +++ b/thoth-export-server/src/xml/onix3_project_muse.rs @@ -743,6 +743,8 @@ mod tests { issn_print: "1234-5678".to_string(), issn_digital: "8765-4321".to_string(), series_url: None, + series_description: None, + series_cfp_url: None, }, }], contributions: vec![],